From 4ea73fc8c5e2c29f35b6a1b66fd845ffdb32929d Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Mon, 19 Dec 2011 10:15:42 +0000 Subject: [PATCH] moving to netgen svn --- contrib/Netgen/libsrc/Makefile.am | 5 + contrib/Netgen/libsrc/csg/Makefile.am | 26 + contrib/Netgen/libsrc/csg/algprim.cpp | 1727 +++++ contrib/Netgen/libsrc/csg/algprim.hpp | 446 ++ contrib/Netgen/libsrc/csg/brick.cpp | 526 ++ contrib/Netgen/libsrc/csg/brick.hpp | 126 + contrib/Netgen/libsrc/csg/bspline2d.cpp | 242 + contrib/Netgen/libsrc/csg/csg.hpp | 44 + contrib/Netgen/libsrc/csg/csgeom.cpp | 1500 +++++ contrib/Netgen/libsrc/csg/csgeom.hpp | 327 + contrib/Netgen/libsrc/csg/csgparser.cpp | 1390 ++++ contrib/Netgen/libsrc/csg/csgparser.hpp | 101 + contrib/Netgen/libsrc/csg/csgpkg.cpp | 700 ++ contrib/Netgen/libsrc/csg/curve2d.cpp | 78 + contrib/Netgen/libsrc/csg/curve2d.hpp | 67 + contrib/Netgen/libsrc/csg/edgeflw.cpp | 1850 ++++++ contrib/Netgen/libsrc/csg/edgeflw.hpp | 110 + contrib/Netgen/libsrc/csg/explicitcurve2d.cpp | 160 + contrib/Netgen/libsrc/csg/explicitcurve2d.hpp | 113 + contrib/Netgen/libsrc/csg/extrusion.cpp | 876 +++ contrib/Netgen/libsrc/csg/extrusion.hpp | 155 + contrib/Netgen/libsrc/csg/gencyl.cpp | 179 + contrib/Netgen/libsrc/csg/gencyl.hpp | 70 + contrib/Netgen/libsrc/csg/genmesh.cpp | 849 +++ contrib/Netgen/libsrc/csg/geoml.hpp | 16 + contrib/Netgen/libsrc/csg/identify.cpp | 1662 +++++ contrib/Netgen/libsrc/csg/identify.hpp | 210 + contrib/Netgen/libsrc/csg/manifold.cpp | 14 + contrib/Netgen/libsrc/csg/manifold.hpp | 29 + contrib/Netgen/libsrc/csg/meshsurf.cpp | 211 + contrib/Netgen/libsrc/csg/meshsurf.hpp | 97 + contrib/Netgen/libsrc/csg/polyhedra.cpp | 738 +++ contrib/Netgen/libsrc/csg/polyhedra.hpp | 104 + contrib/Netgen/libsrc/csg/revolution.cpp | 900 +++ contrib/Netgen/libsrc/csg/revolution.hpp | 153 + contrib/Netgen/libsrc/csg/singularref.cpp | 217 + contrib/Netgen/libsrc/csg/singularref.hpp | 84 + contrib/Netgen/libsrc/csg/solid.cpp | 1732 +++++ contrib/Netgen/libsrc/csg/solid.hpp | 246 + contrib/Netgen/libsrc/csg/specpoin.cpp | 2099 ++++++ contrib/Netgen/libsrc/csg/specpoin.hpp | 191 + contrib/Netgen/libsrc/csg/spline3d.cpp | 355 ++ contrib/Netgen/libsrc/csg/spline3d.hpp | 99 + contrib/Netgen/libsrc/csg/surface.cpp | 568 ++ contrib/Netgen/libsrc/csg/surface.hpp | 374 ++ contrib/Netgen/libsrc/csg/triapprox.cpp | 59 + contrib/Netgen/libsrc/csg/triapprox.hpp | 63 + contrib/Netgen/libsrc/csg/vscsg.cpp | 559 ++ contrib/Netgen/libsrc/csg/vscsg.hpp | 34 + contrib/Netgen/libsrc/general/Makefile.am | 14 + contrib/Netgen/libsrc/general/array.cpp | 75 + contrib/Netgen/libsrc/general/array.hpp | 661 ++ contrib/Netgen/libsrc/general/autodiff.hpp | 351 + contrib/Netgen/libsrc/general/autoptr.hpp | 36 + contrib/Netgen/libsrc/general/bitarray.cpp | 132 + contrib/Netgen/libsrc/general/bitarray.hpp | 227 + contrib/Netgen/libsrc/general/dynamicmem.cpp | 201 + contrib/Netgen/libsrc/general/dynamicmem.hpp | 98 + contrib/Netgen/libsrc/general/flags.cpp | 330 + contrib/Netgen/libsrc/general/flags.hpp | 88 + contrib/Netgen/libsrc/general/hashtabl.cpp | 326 + contrib/Netgen/libsrc/general/hashtabl.hpp | 1362 ++++ .../Netgen/libsrc/general/mpi_interface.hpp | 300 + contrib/Netgen/libsrc/general/myadt.hpp | 48 + contrib/Netgen/libsrc/general/mystring.cpp | 426 ++ contrib/Netgen/libsrc/general/mystring.hpp | 220 + contrib/Netgen/libsrc/general/netgenout.hpp | 187 + contrib/Netgen/libsrc/general/ngexception.cpp | 33 + contrib/Netgen/libsrc/general/ngexception.hpp | 33 + contrib/Netgen/libsrc/general/optmem.cpp | 63 + contrib/Netgen/libsrc/general/optmem.hpp | 62 + contrib/Netgen/libsrc/general/parthreads.cpp | 40 + contrib/Netgen/libsrc/general/parthreads.hpp | 192 + contrib/Netgen/libsrc/general/profiler.cpp | 118 + contrib/Netgen/libsrc/general/profiler.hpp | 66 + contrib/Netgen/libsrc/general/seti.cpp | 70 + contrib/Netgen/libsrc/general/seti.hpp | 50 + contrib/Netgen/libsrc/general/sort.cpp | 75 + contrib/Netgen/libsrc/general/sort.hpp | 46 + contrib/Netgen/libsrc/general/spbita2d.cpp | 172 + contrib/Netgen/libsrc/general/spbita2d.hpp | 59 + contrib/Netgen/libsrc/general/stack.hpp | 114 + contrib/Netgen/libsrc/general/symbolta.cpp | 52 + contrib/Netgen/libsrc/general/symbolta.hpp | 161 + contrib/Netgen/libsrc/general/table.cpp | 214 + contrib/Netgen/libsrc/general/table.hpp | 239 + contrib/Netgen/libsrc/general/template.hpp | 460 ++ contrib/Netgen/libsrc/geom2d/Makefile.am | 14 + contrib/Netgen/libsrc/geom2d/genmesh2d.cpp | 542 ++ contrib/Netgen/libsrc/geom2d/geom2dmesh.cpp | 82 + contrib/Netgen/libsrc/geom2d/geom2dmesh.hpp | 52 + contrib/Netgen/libsrc/geom2d/geom2dpkg.cpp | 72 + contrib/Netgen/libsrc/geom2d/geometry2d.cpp | 938 +++ contrib/Netgen/libsrc/geom2d/geometry2d.hpp | 184 + contrib/Netgen/libsrc/geom2d/spline2d.hpp | 234 + .../Netgen/libsrc/geom2d/splinegeometry2.hpp | 103 + contrib/Netgen/libsrc/geom2d/vsgeom2d.cpp | 110 + contrib/Netgen/libsrc/geom2d/vsgeom2d.hpp | 28 + contrib/Netgen/libsrc/gprim/Makefile.am | 7 + contrib/Netgen/libsrc/gprim/adtree.cpp | 2165 +++++++ contrib/Netgen/libsrc/gprim/adtree.hpp | 486 ++ contrib/Netgen/libsrc/gprim/geom2d.cpp | 489 ++ contrib/Netgen/libsrc/gprim/geom2d.hpp | 886 +++ contrib/Netgen/libsrc/gprim/geom3d.cpp | 731 +++ contrib/Netgen/libsrc/gprim/geom3d.hpp | 746 +++ contrib/Netgen/libsrc/gprim/geomfuncs.cpp | 111 + contrib/Netgen/libsrc/gprim/geomfuncs.hpp | 170 + contrib/Netgen/libsrc/gprim/geomobjects.hpp | 370 ++ contrib/Netgen/libsrc/gprim/geomobjects2.hpp | 366 ++ contrib/Netgen/libsrc/gprim/geomops.hpp | 394 ++ contrib/Netgen/libsrc/gprim/geomops2.hpp | 428 ++ contrib/Netgen/libsrc/gprim/geomtest3d.cpp | 1150 ++++ contrib/Netgen/libsrc/gprim/geomtest3d.hpp | 87 + contrib/Netgen/libsrc/gprim/gprim.hpp | 33 + contrib/Netgen/libsrc/gprim/spline.cpp | 497 ++ contrib/Netgen/libsrc/gprim/spline.hpp | 647 ++ .../Netgen/libsrc/gprim/splinegeometry.cpp | 134 + .../Netgen/libsrc/gprim/splinegeometry.hpp | 68 + contrib/Netgen/libsrc/gprim/transform3d.cpp | 165 + contrib/Netgen/libsrc/gprim/transform3d.hpp | 193 + contrib/Netgen/libsrc/include/Makefile.am | 8 + contrib/Netgen/libsrc/include/acisgeom.hpp | 3 + contrib/Netgen/libsrc/include/csg.hpp | 1 + contrib/Netgen/libsrc/include/geometry2d.hpp | 1 + contrib/Netgen/libsrc/include/gprim.hpp | 1 + contrib/Netgen/libsrc/include/incvis.hpp | 39 + contrib/Netgen/libsrc/include/linalg.hpp | 1 + contrib/Netgen/libsrc/include/meshing.hpp | 1 + contrib/Netgen/libsrc/include/myadt.hpp | 1 + contrib/Netgen/libsrc/include/mydefs.hpp | 49 + contrib/Netgen/libsrc/include/mystdlib.h | 88 + contrib/Netgen/libsrc/include/nginterface.h | 510 ++ .../Netgen/libsrc/include/nginterface_v2.hpp | 175 + contrib/Netgen/libsrc/include/occgeom.hpp | 1 + contrib/Netgen/libsrc/include/opti.hpp | 1 + contrib/Netgen/libsrc/include/parallel.hpp | 1 + .../libsrc/include/parallelinterface.hpp | 49 + contrib/Netgen/libsrc/include/stlgeom.hpp | 1 + contrib/Netgen/libsrc/include/visual.hpp | 1 + contrib/Netgen/libsrc/interface/Makefile.am | 12 + .../Netgen/libsrc/interface/nginterface.cpp | 2448 +++++++ .../libsrc/interface/nginterface_v2.cpp | 221 + .../Netgen/libsrc/interface/read_fnf_mesh.cpp | 451 ++ .../Netgen/libsrc/interface/readtetmesh.cpp | 797 +++ contrib/Netgen/libsrc/interface/readuser.cpp | 422 ++ .../libsrc/interface/writeOpenFOAM15x.cpp | 768 +++ .../Netgen/libsrc/interface/writeabaqus.cpp | 237 + .../Netgen/libsrc/interface/writediffpack.cpp | 296 + .../Netgen/libsrc/interface/writedolfin.cpp | 69 + .../Netgen/libsrc/interface/writeelmer.cpp | 132 + contrib/Netgen/libsrc/interface/writefeap.cpp | 220 + .../Netgen/libsrc/interface/writefluent.cpp | 193 + contrib/Netgen/libsrc/interface/writegmsh.cpp | 200 + .../Netgen/libsrc/interface/writegmsh2.cpp | 261 + contrib/Netgen/libsrc/interface/writejcm.cpp | 430 ++ .../Netgen/libsrc/interface/writepermas.cpp | 208 + .../Netgen/libsrc/interface/writetecplot.cpp | 127 + contrib/Netgen/libsrc/interface/writetet.cpp | 1096 ++++ .../Netgen/libsrc/interface/writetochnog.cpp | 108 + contrib/Netgen/libsrc/interface/writeuser.cpp | 1026 +++ contrib/Netgen/libsrc/interface/writeuser.hpp | 165 + .../Netgen/libsrc/interface/wuchemnitz.cpp | 317 + contrib/Netgen/libsrc/linalg/Makefile.am | 9 + contrib/Netgen/libsrc/linalg/bfgs.cpp | 407 ++ contrib/Netgen/libsrc/linalg/densemat.cpp | 1384 ++++ contrib/Netgen/libsrc/linalg/densemat.hpp | 277 + contrib/Netgen/libsrc/linalg/linalg.hpp | 32 + contrib/Netgen/libsrc/linalg/linopt.cpp | 73 + contrib/Netgen/libsrc/linalg/linsearch.cpp | 349 + contrib/Netgen/libsrc/linalg/opti.hpp | 142 + contrib/Netgen/libsrc/linalg/polynomial.cpp | 198 + contrib/Netgen/libsrc/linalg/polynomial.hpp | 45 + contrib/Netgen/libsrc/linalg/vector.hpp | 161 + contrib/Netgen/libsrc/meshing/Makefile.am | 31 + contrib/Netgen/libsrc/meshing/adfront2.cpp | 508 ++ contrib/Netgen/libsrc/meshing/adfront2.hpp | 282 + contrib/Netgen/libsrc/meshing/adfront3.cpp | 868 +++ contrib/Netgen/libsrc/meshing/adfront3.hpp | 320 + contrib/Netgen/libsrc/meshing/basegeom.cpp | 66 + contrib/Netgen/libsrc/meshing/basegeom.hpp | 50 + contrib/Netgen/libsrc/meshing/bcfunctions.cpp | 468 ++ contrib/Netgen/libsrc/meshing/bcfunctions.hpp | 53 + contrib/Netgen/libsrc/meshing/bisect.cpp | 4071 ++++++++++++ contrib/Netgen/libsrc/meshing/bisect.hpp | 102 + .../Netgen/libsrc/meshing/boundarylayer.cpp | 610 ++ .../Netgen/libsrc/meshing/boundarylayer.hpp | 13 + .../Netgen/libsrc/meshing/classifyhpel.hpp | 1728 +++++ contrib/Netgen/libsrc/meshing/clusters.cpp | 267 + contrib/Netgen/libsrc/meshing/clusters.hpp | 42 + contrib/Netgen/libsrc/meshing/curvedelems.cpp | 3581 +++++++++++ contrib/Netgen/libsrc/meshing/curvedelems.hpp | 223 + contrib/Netgen/libsrc/meshing/delaunay.cpp | 1676 +++++ contrib/Netgen/libsrc/meshing/delaunay2d.cpp | 174 + contrib/Netgen/libsrc/meshing/findip.hpp | 192 + contrib/Netgen/libsrc/meshing/findip2.hpp | 95 + contrib/Netgen/libsrc/meshing/geomsearch.cpp | 263 + contrib/Netgen/libsrc/meshing/geomsearch.hpp | 117 + contrib/Netgen/libsrc/meshing/global.cpp | 59 + contrib/Netgen/libsrc/meshing/global.hpp | 54 + contrib/Netgen/libsrc/meshing/hpref_hex.hpp | 236 + contrib/Netgen/libsrc/meshing/hpref_prism.hpp | 3405 ++++++++++ .../Netgen/libsrc/meshing/hpref_pyramid.hpp | 118 + contrib/Netgen/libsrc/meshing/hpref_quad.hpp | 2082 ++++++ contrib/Netgen/libsrc/meshing/hpref_segm.hpp | 122 + contrib/Netgen/libsrc/meshing/hpref_tet.hpp | 3128 +++++++++ contrib/Netgen/libsrc/meshing/hpref_trig.hpp | 776 +++ .../Netgen/libsrc/meshing/hprefinement.cpp | 1969 ++++++ .../Netgen/libsrc/meshing/hprefinement.hpp | 319 + contrib/Netgen/libsrc/meshing/improve2.cpp | 854 +++ contrib/Netgen/libsrc/meshing/improve2.hpp | 102 + contrib/Netgen/libsrc/meshing/improve2gen.cpp | 455 ++ contrib/Netgen/libsrc/meshing/improve3.cpp | 2779 ++++++++ contrib/Netgen/libsrc/meshing/improve3.hpp | 125 + contrib/Netgen/libsrc/meshing/localh.cpp | 708 +++ contrib/Netgen/libsrc/meshing/localh.hpp | 187 + contrib/Netgen/libsrc/meshing/meshclass.cpp | 5648 +++++++++++++++++ contrib/Netgen/libsrc/meshing/meshclass.hpp | 770 +++ contrib/Netgen/libsrc/meshing/meshfunc.cpp | 717 +++ contrib/Netgen/libsrc/meshing/meshfunc.hpp | 41 + contrib/Netgen/libsrc/meshing/meshfunc2d.cpp | 61 + contrib/Netgen/libsrc/meshing/meshing.hpp | 71 + contrib/Netgen/libsrc/meshing/meshing2.cpp | 1957 ++++++ contrib/Netgen/libsrc/meshing/meshing2.hpp | 164 + contrib/Netgen/libsrc/meshing/meshing3.cpp | 1264 ++++ contrib/Netgen/libsrc/meshing/meshing3.hpp | 130 + contrib/Netgen/libsrc/meshing/meshtool.cpp | 1015 +++ contrib/Netgen/libsrc/meshing/meshtool.hpp | 81 + contrib/Netgen/libsrc/meshing/meshtype.cpp | 2680 ++++++++ contrib/Netgen/libsrc/meshing/meshtype.hpp | 1306 ++++ contrib/Netgen/libsrc/meshing/msghandler.cpp | 227 + contrib/Netgen/libsrc/meshing/msghandler.hpp | 57 + contrib/Netgen/libsrc/meshing/netrule2.cpp | 222 + contrib/Netgen/libsrc/meshing/netrule3.cpp | 1138 ++++ .../Netgen/libsrc/meshing/parallelmesh.cpp | 1173 ++++ contrib/Netgen/libsrc/meshing/paralleltop.cpp | 896 +++ contrib/Netgen/libsrc/meshing/paralleltop.hpp | 156 + contrib/Netgen/libsrc/meshing/parser2.cpp | 605 ++ contrib/Netgen/libsrc/meshing/parser3.cpp | 1019 +++ contrib/Netgen/libsrc/meshing/prism2rls.cpp | 457 ++ contrib/Netgen/libsrc/meshing/prism2rls_2.cpp | 446 ++ contrib/Netgen/libsrc/meshing/pyramid2rls.cpp | 309 + contrib/Netgen/libsrc/meshing/pyramidrls.cpp | 263 + contrib/Netgen/libsrc/meshing/quadrls.cpp | 887 +++ contrib/Netgen/libsrc/meshing/refine.cpp | 757 +++ contrib/Netgen/libsrc/meshing/ruler2.cpp | 719 +++ contrib/Netgen/libsrc/meshing/ruler2.hpp | 169 + contrib/Netgen/libsrc/meshing/ruler3.cpp | 1136 ++++ contrib/Netgen/libsrc/meshing/ruler3.hpp | 210 + contrib/Netgen/libsrc/meshing/secondorder.cpp | 490 ++ .../Netgen/libsrc/meshing/smoothing2.5.cpp | 265 + contrib/Netgen/libsrc/meshing/smoothing2.cpp | 903 +++ contrib/Netgen/libsrc/meshing/smoothing3.cpp | 1838 ++++++ contrib/Netgen/libsrc/meshing/specials.cpp | 193 + contrib/Netgen/libsrc/meshing/specials.hpp | 16 + contrib/Netgen/libsrc/meshing/tetrarls.cpp | 1466 +++++ contrib/Netgen/libsrc/meshing/topology.cpp | 1726 +++++ contrib/Netgen/libsrc/meshing/topology.hpp | 683 ++ contrib/Netgen/libsrc/meshing/triarls.cpp | 468 ++ contrib/Netgen/libsrc/meshing/validate.cpp | 591 ++ contrib/Netgen/libsrc/meshing/validate.hpp | 21 + contrib/Netgen/libsrc/meshing/zrefine.cpp | 740 +++ contrib/Netgen/libsrc/occ/Makefile.am | 28 + .../Netgen/libsrc/occ/Partition_Inter2d.cxx | 678 ++ .../Netgen/libsrc/occ/Partition_Inter2d.hxx | 110 + .../Netgen/libsrc/occ/Partition_Inter2d.ixx | 32 + .../Netgen/libsrc/occ/Partition_Inter2d.jxx | 50 + .../Netgen/libsrc/occ/Partition_Inter3d.cxx | 947 +++ .../Netgen/libsrc/occ/Partition_Inter3d.hxx | 143 + .../Netgen/libsrc/occ/Partition_Inter3d.ixx | 31 + .../Netgen/libsrc/occ/Partition_Inter3d.jxx | 53 + contrib/Netgen/libsrc/occ/Partition_Loop.cxx | 473 ++ contrib/Netgen/libsrc/occ/Partition_Loop.hxx | 118 + contrib/Netgen/libsrc/occ/Partition_Loop.ixx | 31 + contrib/Netgen/libsrc/occ/Partition_Loop.jxx | 41 + .../Netgen/libsrc/occ/Partition_Loop2d.cxx | 1145 ++++ .../Netgen/libsrc/occ/Partition_Loop2d.hxx | 106 + .../Netgen/libsrc/occ/Partition_Loop2d.ixx | 14 + .../Netgen/libsrc/occ/Partition_Loop2d.jxx | 24 + .../Netgen/libsrc/occ/Partition_Loop3d.cxx | 356 ++ .../Netgen/libsrc/occ/Partition_Loop3d.hxx | 102 + .../Netgen/libsrc/occ/Partition_Loop3d.ixx | 14 + .../Netgen/libsrc/occ/Partition_Loop3d.jxx | 30 + .../Netgen/libsrc/occ/Partition_Spliter.cxx | 2168 +++++++ .../Netgen/libsrc/occ/Partition_Spliter.hxx | 150 + .../Netgen/libsrc/occ/Partition_Spliter.ixx | 31 + .../Netgen/libsrc/occ/Partition_Spliter.jxx | 41 + contrib/Netgen/libsrc/occ/occconstruction.cpp | 157 + contrib/Netgen/libsrc/occ/occgenmesh.cpp | 1460 +++++ contrib/Netgen/libsrc/occ/occgeom.cpp | 1608 +++++ contrib/Netgen/libsrc/occ/occgeom.hpp | 451 ++ contrib/Netgen/libsrc/occ/occmeshsurf.cpp | 735 +++ contrib/Netgen/libsrc/occ/occmeshsurf.hpp | 203 + contrib/Netgen/libsrc/occ/occpkg.cpp | 1020 +++ contrib/Netgen/libsrc/occ/utilities.h | 112 + contrib/Netgen/libsrc/occ/vsocc.cpp | 764 +++ contrib/Netgen/libsrc/occ/vsocc.hpp | 33 + contrib/Netgen/libsrc/stlgeom/Makefile.am | 15 + .../Netgen/libsrc/stlgeom/meshstlsurface.cpp | 1133 ++++ .../Netgen/libsrc/stlgeom/meshstlsurface.hpp | 121 + contrib/Netgen/libsrc/stlgeom/stlgeom.cpp | 3506 ++++++++++ contrib/Netgen/libsrc/stlgeom/stlgeom.hpp | 459 ++ .../Netgen/libsrc/stlgeom/stlgeomchart.cpp | 798 +++ contrib/Netgen/libsrc/stlgeom/stlgeommesh.cpp | 1590 +++++ contrib/Netgen/libsrc/stlgeom/stlline.cpp | 780 +++ contrib/Netgen/libsrc/stlgeom/stlline.hpp | 188 + contrib/Netgen/libsrc/stlgeom/stlpkg.cpp | 622 ++ contrib/Netgen/libsrc/stlgeom/stltool.cpp | 1287 ++++ contrib/Netgen/libsrc/stlgeom/stltool.hpp | 271 + contrib/Netgen/libsrc/stlgeom/stltopology.cpp | 1067 ++++ contrib/Netgen/libsrc/stlgeom/stltopology.hpp | 362 ++ contrib/Netgen/libsrc/stlgeom/vsstl.cpp | 1212 ++++ contrib/Netgen/libsrc/stlgeom/vsstl.hpp | 53 + .../Netgen/libsrc/visualization/Makefile.am | 11 + .../libsrc/visualization/importsolution.cpp | 129 + .../Netgen/libsrc/visualization/meshdoc.cpp | 614 ++ .../Netgen/libsrc/visualization/meshdoc.hpp | 37 + .../Netgen/libsrc/visualization/mvdraw.cpp | 806 +++ .../Netgen/libsrc/visualization/mvdraw.hpp | 245 + .../Netgen/libsrc/visualization/soldata.hpp | 111 + .../libsrc/visualization/stlmeshing.cpp | 1076 ++++ .../Netgen/libsrc/visualization/vispar.hpp | 106 + .../Netgen/libsrc/visualization/visual.hpp | 35 + contrib/Netgen/libsrc/visualization/vscsg.cpp | 272 + .../libsrc/visualization/vsfieldlines.cpp | 729 +++ .../Netgen/libsrc/visualization/vsmesh.cpp | 3445 ++++++++++ contrib/Netgen/libsrc/visualization/vsocc.cpp | 762 +++ .../libsrc/visualization/vssolution.cpp | 4537 +++++++++++++ .../libsrc/visualization/vssolution.hpp | 430 ++ 328 files changed, 166474 insertions(+) create mode 100644 contrib/Netgen/libsrc/Makefile.am create mode 100644 contrib/Netgen/libsrc/csg/Makefile.am create mode 100644 contrib/Netgen/libsrc/csg/algprim.cpp create mode 100644 contrib/Netgen/libsrc/csg/algprim.hpp create mode 100644 contrib/Netgen/libsrc/csg/brick.cpp create mode 100644 contrib/Netgen/libsrc/csg/brick.hpp create mode 100644 contrib/Netgen/libsrc/csg/bspline2d.cpp create mode 100644 contrib/Netgen/libsrc/csg/csg.hpp create mode 100644 contrib/Netgen/libsrc/csg/csgeom.cpp create mode 100644 contrib/Netgen/libsrc/csg/csgeom.hpp create mode 100644 contrib/Netgen/libsrc/csg/csgparser.cpp create mode 100644 contrib/Netgen/libsrc/csg/csgparser.hpp create mode 100644 contrib/Netgen/libsrc/csg/csgpkg.cpp create mode 100644 contrib/Netgen/libsrc/csg/curve2d.cpp create mode 100644 contrib/Netgen/libsrc/csg/curve2d.hpp create mode 100644 contrib/Netgen/libsrc/csg/edgeflw.cpp create mode 100644 contrib/Netgen/libsrc/csg/edgeflw.hpp create mode 100644 contrib/Netgen/libsrc/csg/explicitcurve2d.cpp create mode 100644 contrib/Netgen/libsrc/csg/explicitcurve2d.hpp create mode 100644 contrib/Netgen/libsrc/csg/extrusion.cpp create mode 100644 contrib/Netgen/libsrc/csg/extrusion.hpp create mode 100644 contrib/Netgen/libsrc/csg/gencyl.cpp create mode 100644 contrib/Netgen/libsrc/csg/gencyl.hpp create mode 100644 contrib/Netgen/libsrc/csg/genmesh.cpp create mode 100644 contrib/Netgen/libsrc/csg/geoml.hpp create mode 100644 contrib/Netgen/libsrc/csg/identify.cpp create mode 100644 contrib/Netgen/libsrc/csg/identify.hpp create mode 100644 contrib/Netgen/libsrc/csg/manifold.cpp create mode 100644 contrib/Netgen/libsrc/csg/manifold.hpp create mode 100644 contrib/Netgen/libsrc/csg/meshsurf.cpp create mode 100644 contrib/Netgen/libsrc/csg/meshsurf.hpp create mode 100644 contrib/Netgen/libsrc/csg/polyhedra.cpp create mode 100644 contrib/Netgen/libsrc/csg/polyhedra.hpp create mode 100644 contrib/Netgen/libsrc/csg/revolution.cpp create mode 100644 contrib/Netgen/libsrc/csg/revolution.hpp create mode 100644 contrib/Netgen/libsrc/csg/singularref.cpp create mode 100644 contrib/Netgen/libsrc/csg/singularref.hpp create mode 100644 contrib/Netgen/libsrc/csg/solid.cpp create mode 100644 contrib/Netgen/libsrc/csg/solid.hpp create mode 100644 contrib/Netgen/libsrc/csg/specpoin.cpp create mode 100644 contrib/Netgen/libsrc/csg/specpoin.hpp create mode 100644 contrib/Netgen/libsrc/csg/spline3d.cpp create mode 100644 contrib/Netgen/libsrc/csg/spline3d.hpp create mode 100644 contrib/Netgen/libsrc/csg/surface.cpp create mode 100644 contrib/Netgen/libsrc/csg/surface.hpp create mode 100644 contrib/Netgen/libsrc/csg/triapprox.cpp create mode 100644 contrib/Netgen/libsrc/csg/triapprox.hpp create mode 100644 contrib/Netgen/libsrc/csg/vscsg.cpp create mode 100644 contrib/Netgen/libsrc/csg/vscsg.hpp create mode 100644 contrib/Netgen/libsrc/general/Makefile.am create mode 100644 contrib/Netgen/libsrc/general/array.cpp create mode 100644 contrib/Netgen/libsrc/general/array.hpp create mode 100644 contrib/Netgen/libsrc/general/autodiff.hpp create mode 100644 contrib/Netgen/libsrc/general/autoptr.hpp create mode 100644 contrib/Netgen/libsrc/general/bitarray.cpp create mode 100644 contrib/Netgen/libsrc/general/bitarray.hpp create mode 100644 contrib/Netgen/libsrc/general/dynamicmem.cpp create mode 100644 contrib/Netgen/libsrc/general/dynamicmem.hpp create mode 100644 contrib/Netgen/libsrc/general/flags.cpp create mode 100644 contrib/Netgen/libsrc/general/flags.hpp create mode 100644 contrib/Netgen/libsrc/general/hashtabl.cpp create mode 100644 contrib/Netgen/libsrc/general/hashtabl.hpp create mode 100644 contrib/Netgen/libsrc/general/mpi_interface.hpp create mode 100644 contrib/Netgen/libsrc/general/myadt.hpp create mode 100644 contrib/Netgen/libsrc/general/mystring.cpp create mode 100644 contrib/Netgen/libsrc/general/mystring.hpp create mode 100644 contrib/Netgen/libsrc/general/netgenout.hpp create mode 100644 contrib/Netgen/libsrc/general/ngexception.cpp create mode 100644 contrib/Netgen/libsrc/general/ngexception.hpp create mode 100644 contrib/Netgen/libsrc/general/optmem.cpp create mode 100644 contrib/Netgen/libsrc/general/optmem.hpp create mode 100644 contrib/Netgen/libsrc/general/parthreads.cpp create mode 100644 contrib/Netgen/libsrc/general/parthreads.hpp create mode 100644 contrib/Netgen/libsrc/general/profiler.cpp create mode 100644 contrib/Netgen/libsrc/general/profiler.hpp create mode 100644 contrib/Netgen/libsrc/general/seti.cpp create mode 100644 contrib/Netgen/libsrc/general/seti.hpp create mode 100644 contrib/Netgen/libsrc/general/sort.cpp create mode 100644 contrib/Netgen/libsrc/general/sort.hpp create mode 100644 contrib/Netgen/libsrc/general/spbita2d.cpp create mode 100644 contrib/Netgen/libsrc/general/spbita2d.hpp create mode 100644 contrib/Netgen/libsrc/general/stack.hpp create mode 100644 contrib/Netgen/libsrc/general/symbolta.cpp create mode 100644 contrib/Netgen/libsrc/general/symbolta.hpp create mode 100644 contrib/Netgen/libsrc/general/table.cpp create mode 100644 contrib/Netgen/libsrc/general/table.hpp create mode 100644 contrib/Netgen/libsrc/general/template.hpp create mode 100644 contrib/Netgen/libsrc/geom2d/Makefile.am create mode 100644 contrib/Netgen/libsrc/geom2d/genmesh2d.cpp create mode 100644 contrib/Netgen/libsrc/geom2d/geom2dmesh.cpp create mode 100644 contrib/Netgen/libsrc/geom2d/geom2dmesh.hpp create mode 100644 contrib/Netgen/libsrc/geom2d/geom2dpkg.cpp create mode 100644 contrib/Netgen/libsrc/geom2d/geometry2d.cpp create mode 100644 contrib/Netgen/libsrc/geom2d/geometry2d.hpp create mode 100644 contrib/Netgen/libsrc/geom2d/spline2d.hpp create mode 100644 contrib/Netgen/libsrc/geom2d/splinegeometry2.hpp create mode 100644 contrib/Netgen/libsrc/geom2d/vsgeom2d.cpp create mode 100644 contrib/Netgen/libsrc/geom2d/vsgeom2d.hpp create mode 100644 contrib/Netgen/libsrc/gprim/Makefile.am create mode 100644 contrib/Netgen/libsrc/gprim/adtree.cpp create mode 100644 contrib/Netgen/libsrc/gprim/adtree.hpp create mode 100644 contrib/Netgen/libsrc/gprim/geom2d.cpp create mode 100644 contrib/Netgen/libsrc/gprim/geom2d.hpp create mode 100644 contrib/Netgen/libsrc/gprim/geom3d.cpp create mode 100644 contrib/Netgen/libsrc/gprim/geom3d.hpp create mode 100644 contrib/Netgen/libsrc/gprim/geomfuncs.cpp create mode 100644 contrib/Netgen/libsrc/gprim/geomfuncs.hpp create mode 100644 contrib/Netgen/libsrc/gprim/geomobjects.hpp create mode 100644 contrib/Netgen/libsrc/gprim/geomobjects2.hpp create mode 100644 contrib/Netgen/libsrc/gprim/geomops.hpp create mode 100644 contrib/Netgen/libsrc/gprim/geomops2.hpp create mode 100644 contrib/Netgen/libsrc/gprim/geomtest3d.cpp create mode 100644 contrib/Netgen/libsrc/gprim/geomtest3d.hpp create mode 100644 contrib/Netgen/libsrc/gprim/gprim.hpp create mode 100644 contrib/Netgen/libsrc/gprim/spline.cpp create mode 100644 contrib/Netgen/libsrc/gprim/spline.hpp create mode 100644 contrib/Netgen/libsrc/gprim/splinegeometry.cpp create mode 100644 contrib/Netgen/libsrc/gprim/splinegeometry.hpp create mode 100644 contrib/Netgen/libsrc/gprim/transform3d.cpp create mode 100644 contrib/Netgen/libsrc/gprim/transform3d.hpp create mode 100644 contrib/Netgen/libsrc/include/Makefile.am create mode 100644 contrib/Netgen/libsrc/include/acisgeom.hpp create mode 100644 contrib/Netgen/libsrc/include/csg.hpp create mode 100644 contrib/Netgen/libsrc/include/geometry2d.hpp create mode 100644 contrib/Netgen/libsrc/include/gprim.hpp create mode 100644 contrib/Netgen/libsrc/include/incvis.hpp create mode 100644 contrib/Netgen/libsrc/include/linalg.hpp create mode 100644 contrib/Netgen/libsrc/include/meshing.hpp create mode 100644 contrib/Netgen/libsrc/include/myadt.hpp create mode 100644 contrib/Netgen/libsrc/include/mydefs.hpp create mode 100644 contrib/Netgen/libsrc/include/mystdlib.h create mode 100644 contrib/Netgen/libsrc/include/nginterface.h create mode 100644 contrib/Netgen/libsrc/include/nginterface_v2.hpp create mode 100644 contrib/Netgen/libsrc/include/occgeom.hpp create mode 100644 contrib/Netgen/libsrc/include/opti.hpp create mode 100644 contrib/Netgen/libsrc/include/parallel.hpp create mode 100644 contrib/Netgen/libsrc/include/parallelinterface.hpp create mode 100644 contrib/Netgen/libsrc/include/stlgeom.hpp create mode 100644 contrib/Netgen/libsrc/include/visual.hpp create mode 100644 contrib/Netgen/libsrc/interface/Makefile.am create mode 100644 contrib/Netgen/libsrc/interface/nginterface.cpp create mode 100644 contrib/Netgen/libsrc/interface/nginterface_v2.cpp create mode 100644 contrib/Netgen/libsrc/interface/read_fnf_mesh.cpp create mode 100644 contrib/Netgen/libsrc/interface/readtetmesh.cpp create mode 100644 contrib/Netgen/libsrc/interface/readuser.cpp create mode 100644 contrib/Netgen/libsrc/interface/writeOpenFOAM15x.cpp create mode 100644 contrib/Netgen/libsrc/interface/writeabaqus.cpp create mode 100644 contrib/Netgen/libsrc/interface/writediffpack.cpp create mode 100644 contrib/Netgen/libsrc/interface/writedolfin.cpp create mode 100644 contrib/Netgen/libsrc/interface/writeelmer.cpp create mode 100644 contrib/Netgen/libsrc/interface/writefeap.cpp create mode 100644 contrib/Netgen/libsrc/interface/writefluent.cpp create mode 100644 contrib/Netgen/libsrc/interface/writegmsh.cpp create mode 100644 contrib/Netgen/libsrc/interface/writegmsh2.cpp create mode 100644 contrib/Netgen/libsrc/interface/writejcm.cpp create mode 100644 contrib/Netgen/libsrc/interface/writepermas.cpp create mode 100644 contrib/Netgen/libsrc/interface/writetecplot.cpp create mode 100644 contrib/Netgen/libsrc/interface/writetet.cpp create mode 100644 contrib/Netgen/libsrc/interface/writetochnog.cpp create mode 100644 contrib/Netgen/libsrc/interface/writeuser.cpp create mode 100644 contrib/Netgen/libsrc/interface/writeuser.hpp create mode 100644 contrib/Netgen/libsrc/interface/wuchemnitz.cpp create mode 100644 contrib/Netgen/libsrc/linalg/Makefile.am create mode 100644 contrib/Netgen/libsrc/linalg/bfgs.cpp create mode 100644 contrib/Netgen/libsrc/linalg/densemat.cpp create mode 100644 contrib/Netgen/libsrc/linalg/densemat.hpp create mode 100644 contrib/Netgen/libsrc/linalg/linalg.hpp create mode 100644 contrib/Netgen/libsrc/linalg/linopt.cpp create mode 100644 contrib/Netgen/libsrc/linalg/linsearch.cpp create mode 100644 contrib/Netgen/libsrc/linalg/opti.hpp create mode 100644 contrib/Netgen/libsrc/linalg/polynomial.cpp create mode 100644 contrib/Netgen/libsrc/linalg/polynomial.hpp create mode 100644 contrib/Netgen/libsrc/linalg/vector.hpp create mode 100644 contrib/Netgen/libsrc/meshing/Makefile.am create mode 100644 contrib/Netgen/libsrc/meshing/adfront2.cpp create mode 100644 contrib/Netgen/libsrc/meshing/adfront2.hpp create mode 100644 contrib/Netgen/libsrc/meshing/adfront3.cpp create mode 100644 contrib/Netgen/libsrc/meshing/adfront3.hpp create mode 100644 contrib/Netgen/libsrc/meshing/basegeom.cpp create mode 100644 contrib/Netgen/libsrc/meshing/basegeom.hpp create mode 100644 contrib/Netgen/libsrc/meshing/bcfunctions.cpp create mode 100644 contrib/Netgen/libsrc/meshing/bcfunctions.hpp create mode 100644 contrib/Netgen/libsrc/meshing/bisect.cpp create mode 100644 contrib/Netgen/libsrc/meshing/bisect.hpp create mode 100644 contrib/Netgen/libsrc/meshing/boundarylayer.cpp create mode 100644 contrib/Netgen/libsrc/meshing/boundarylayer.hpp create mode 100644 contrib/Netgen/libsrc/meshing/classifyhpel.hpp create mode 100644 contrib/Netgen/libsrc/meshing/clusters.cpp create mode 100644 contrib/Netgen/libsrc/meshing/clusters.hpp create mode 100644 contrib/Netgen/libsrc/meshing/curvedelems.cpp create mode 100644 contrib/Netgen/libsrc/meshing/curvedelems.hpp create mode 100644 contrib/Netgen/libsrc/meshing/delaunay.cpp create mode 100644 contrib/Netgen/libsrc/meshing/delaunay2d.cpp create mode 100644 contrib/Netgen/libsrc/meshing/findip.hpp create mode 100644 contrib/Netgen/libsrc/meshing/findip2.hpp create mode 100644 contrib/Netgen/libsrc/meshing/geomsearch.cpp create mode 100644 contrib/Netgen/libsrc/meshing/geomsearch.hpp create mode 100644 contrib/Netgen/libsrc/meshing/global.cpp create mode 100644 contrib/Netgen/libsrc/meshing/global.hpp create mode 100644 contrib/Netgen/libsrc/meshing/hpref_hex.hpp create mode 100644 contrib/Netgen/libsrc/meshing/hpref_prism.hpp create mode 100644 contrib/Netgen/libsrc/meshing/hpref_pyramid.hpp create mode 100644 contrib/Netgen/libsrc/meshing/hpref_quad.hpp create mode 100644 contrib/Netgen/libsrc/meshing/hpref_segm.hpp create mode 100644 contrib/Netgen/libsrc/meshing/hpref_tet.hpp create mode 100644 contrib/Netgen/libsrc/meshing/hpref_trig.hpp create mode 100644 contrib/Netgen/libsrc/meshing/hprefinement.cpp create mode 100644 contrib/Netgen/libsrc/meshing/hprefinement.hpp create mode 100644 contrib/Netgen/libsrc/meshing/improve2.cpp create mode 100644 contrib/Netgen/libsrc/meshing/improve2.hpp create mode 100644 contrib/Netgen/libsrc/meshing/improve2gen.cpp create mode 100644 contrib/Netgen/libsrc/meshing/improve3.cpp create mode 100644 contrib/Netgen/libsrc/meshing/improve3.hpp create mode 100644 contrib/Netgen/libsrc/meshing/localh.cpp create mode 100644 contrib/Netgen/libsrc/meshing/localh.hpp create mode 100644 contrib/Netgen/libsrc/meshing/meshclass.cpp create mode 100644 contrib/Netgen/libsrc/meshing/meshclass.hpp create mode 100644 contrib/Netgen/libsrc/meshing/meshfunc.cpp create mode 100644 contrib/Netgen/libsrc/meshing/meshfunc.hpp create mode 100644 contrib/Netgen/libsrc/meshing/meshfunc2d.cpp create mode 100644 contrib/Netgen/libsrc/meshing/meshing.hpp create mode 100644 contrib/Netgen/libsrc/meshing/meshing2.cpp create mode 100644 contrib/Netgen/libsrc/meshing/meshing2.hpp create mode 100644 contrib/Netgen/libsrc/meshing/meshing3.cpp create mode 100644 contrib/Netgen/libsrc/meshing/meshing3.hpp create mode 100644 contrib/Netgen/libsrc/meshing/meshtool.cpp create mode 100644 contrib/Netgen/libsrc/meshing/meshtool.hpp create mode 100644 contrib/Netgen/libsrc/meshing/meshtype.cpp create mode 100644 contrib/Netgen/libsrc/meshing/meshtype.hpp create mode 100644 contrib/Netgen/libsrc/meshing/msghandler.cpp create mode 100644 contrib/Netgen/libsrc/meshing/msghandler.hpp create mode 100644 contrib/Netgen/libsrc/meshing/netrule2.cpp create mode 100644 contrib/Netgen/libsrc/meshing/netrule3.cpp create mode 100644 contrib/Netgen/libsrc/meshing/parallelmesh.cpp create mode 100644 contrib/Netgen/libsrc/meshing/paralleltop.cpp create mode 100644 contrib/Netgen/libsrc/meshing/paralleltop.hpp create mode 100644 contrib/Netgen/libsrc/meshing/parser2.cpp create mode 100644 contrib/Netgen/libsrc/meshing/parser3.cpp create mode 100644 contrib/Netgen/libsrc/meshing/prism2rls.cpp create mode 100644 contrib/Netgen/libsrc/meshing/prism2rls_2.cpp create mode 100644 contrib/Netgen/libsrc/meshing/pyramid2rls.cpp create mode 100644 contrib/Netgen/libsrc/meshing/pyramidrls.cpp create mode 100644 contrib/Netgen/libsrc/meshing/quadrls.cpp create mode 100644 contrib/Netgen/libsrc/meshing/refine.cpp create mode 100644 contrib/Netgen/libsrc/meshing/ruler2.cpp create mode 100644 contrib/Netgen/libsrc/meshing/ruler2.hpp create mode 100644 contrib/Netgen/libsrc/meshing/ruler3.cpp create mode 100644 contrib/Netgen/libsrc/meshing/ruler3.hpp create mode 100644 contrib/Netgen/libsrc/meshing/secondorder.cpp create mode 100644 contrib/Netgen/libsrc/meshing/smoothing2.5.cpp create mode 100644 contrib/Netgen/libsrc/meshing/smoothing2.cpp create mode 100644 contrib/Netgen/libsrc/meshing/smoothing3.cpp create mode 100644 contrib/Netgen/libsrc/meshing/specials.cpp create mode 100644 contrib/Netgen/libsrc/meshing/specials.hpp create mode 100644 contrib/Netgen/libsrc/meshing/tetrarls.cpp create mode 100644 contrib/Netgen/libsrc/meshing/topology.cpp create mode 100644 contrib/Netgen/libsrc/meshing/topology.hpp create mode 100644 contrib/Netgen/libsrc/meshing/triarls.cpp create mode 100644 contrib/Netgen/libsrc/meshing/validate.cpp create mode 100644 contrib/Netgen/libsrc/meshing/validate.hpp create mode 100644 contrib/Netgen/libsrc/meshing/zrefine.cpp create mode 100644 contrib/Netgen/libsrc/occ/Makefile.am create mode 100644 contrib/Netgen/libsrc/occ/Partition_Inter2d.cxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Inter2d.hxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Inter2d.ixx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Inter2d.jxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Inter3d.cxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Inter3d.hxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Inter3d.ixx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Inter3d.jxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Loop.cxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Loop.hxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Loop.ixx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Loop.jxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Loop2d.cxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Loop2d.hxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Loop2d.ixx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Loop2d.jxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Loop3d.cxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Loop3d.hxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Loop3d.ixx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Loop3d.jxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Spliter.cxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Spliter.hxx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Spliter.ixx create mode 100644 contrib/Netgen/libsrc/occ/Partition_Spliter.jxx create mode 100644 contrib/Netgen/libsrc/occ/occconstruction.cpp create mode 100644 contrib/Netgen/libsrc/occ/occgenmesh.cpp create mode 100644 contrib/Netgen/libsrc/occ/occgeom.cpp create mode 100644 contrib/Netgen/libsrc/occ/occgeom.hpp create mode 100644 contrib/Netgen/libsrc/occ/occmeshsurf.cpp create mode 100644 contrib/Netgen/libsrc/occ/occmeshsurf.hpp create mode 100644 contrib/Netgen/libsrc/occ/occpkg.cpp create mode 100644 contrib/Netgen/libsrc/occ/utilities.h create mode 100644 contrib/Netgen/libsrc/occ/vsocc.cpp create mode 100644 contrib/Netgen/libsrc/occ/vsocc.hpp create mode 100644 contrib/Netgen/libsrc/stlgeom/Makefile.am create mode 100644 contrib/Netgen/libsrc/stlgeom/meshstlsurface.cpp create mode 100644 contrib/Netgen/libsrc/stlgeom/meshstlsurface.hpp create mode 100644 contrib/Netgen/libsrc/stlgeom/stlgeom.cpp create mode 100644 contrib/Netgen/libsrc/stlgeom/stlgeom.hpp create mode 100644 contrib/Netgen/libsrc/stlgeom/stlgeomchart.cpp create mode 100644 contrib/Netgen/libsrc/stlgeom/stlgeommesh.cpp create mode 100644 contrib/Netgen/libsrc/stlgeom/stlline.cpp create mode 100644 contrib/Netgen/libsrc/stlgeom/stlline.hpp create mode 100644 contrib/Netgen/libsrc/stlgeom/stlpkg.cpp create mode 100644 contrib/Netgen/libsrc/stlgeom/stltool.cpp create mode 100644 contrib/Netgen/libsrc/stlgeom/stltool.hpp create mode 100644 contrib/Netgen/libsrc/stlgeom/stltopology.cpp create mode 100644 contrib/Netgen/libsrc/stlgeom/stltopology.hpp create mode 100644 contrib/Netgen/libsrc/stlgeom/vsstl.cpp create mode 100644 contrib/Netgen/libsrc/stlgeom/vsstl.hpp create mode 100644 contrib/Netgen/libsrc/visualization/Makefile.am create mode 100644 contrib/Netgen/libsrc/visualization/importsolution.cpp create mode 100644 contrib/Netgen/libsrc/visualization/meshdoc.cpp create mode 100644 contrib/Netgen/libsrc/visualization/meshdoc.hpp create mode 100644 contrib/Netgen/libsrc/visualization/mvdraw.cpp create mode 100644 contrib/Netgen/libsrc/visualization/mvdraw.hpp create mode 100644 contrib/Netgen/libsrc/visualization/soldata.hpp create mode 100644 contrib/Netgen/libsrc/visualization/stlmeshing.cpp create mode 100644 contrib/Netgen/libsrc/visualization/vispar.hpp create mode 100644 contrib/Netgen/libsrc/visualization/visual.hpp create mode 100644 contrib/Netgen/libsrc/visualization/vscsg.cpp create mode 100644 contrib/Netgen/libsrc/visualization/vsfieldlines.cpp create mode 100644 contrib/Netgen/libsrc/visualization/vsmesh.cpp create mode 100644 contrib/Netgen/libsrc/visualization/vsocc.cpp create mode 100644 contrib/Netgen/libsrc/visualization/vssolution.cpp create mode 100644 contrib/Netgen/libsrc/visualization/vssolution.hpp diff --git a/contrib/Netgen/libsrc/Makefile.am b/contrib/Netgen/libsrc/Makefile.am new file mode 100644 index 0000000000..8337b4b7f7 --- /dev/null +++ b/contrib/Netgen/libsrc/Makefile.am @@ -0,0 +1,5 @@ +AM_CPPFLAGS = + +METASOURCES = AUTO + +SUBDIRS = general gprim linalg include meshing interface csg geom2d occ stlgeom visualization diff --git a/contrib/Netgen/libsrc/csg/Makefile.am b/contrib/Netgen/libsrc/csg/Makefile.am new file mode 100644 index 0000000000..acf35b00d9 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/Makefile.am @@ -0,0 +1,26 @@ +noinst_HEADERS = algprim.hpp csgparser.hpp extrusion.hpp manifold.hpp \ +singularref.hpp surface.hpp brick.hpp curve2d.hpp gencyl.hpp \ +meshsurf.hpp solid.hpp triapprox.hpp csgeom.hpp edgeflw.hpp geoml.hpp \ +polyhedra.hpp specpoin.hpp csg.hpp explicitcurve2d.hpp identify.hpp \ +revolution.hpp spline3d.hpp vscsg.hpp + + +AM_CPPFLAGS = -I$(top_srcdir)/libsrc/include $(TCL_INCLUDES) +METASOURCES = AUTO + +lib_LTLIBRARIES = libcsg.la libcsgvis.la + + +libcsg_la_SOURCES = 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 + + +libcsgvis_la_SOURCES = vscsg.cpp csgpkg.cpp + + +libcsgvis_la_LIBADD = libcsg.la +# $(top_builddir)/libsrc/geom2d/libgeom2d.la + diff --git a/contrib/Netgen/libsrc/csg/algprim.cpp b/contrib/Netgen/libsrc/csg/algprim.cpp new file mode 100644 index 0000000000..09bad01327 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/algprim.cpp @@ -0,0 +1,1727 @@ +#include <mystdlib.h> + + +#include <linalg.hpp> +#include <csg.hpp> + + +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 :: 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<double> & 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<double> & 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<const Plane*>(&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<double> & 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<double> & 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<const Sphere*> (&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 + { + return c + Vec<3> (r, 0, 0); + } + + + 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<double> & 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; + + // ( <x,x> - 2 <x,a> + <a,a> + // - <x,vab>^2 + 2 <x,vab> <a, vab> - <a, vab>^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<double> & 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<double> & 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); + } + + + int Cylinder :: IsIdentic (const Surface & s2, int & inv, double eps) const + { + const Cylinder * cyl2 = dynamic_cast<const Cylinder*> (&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(); + + // ( <x,x> - 2 <x,a> + <a,a> + // - <x,vab>^2 + 2 <x,vab> <a, vab> - <a, vab>^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<double> & coeffs) + { + SetPrimitiveData(coeffs); + } + + + + void EllipticCylinder :: GetPrimitiveData (const char *& classname, Array<double> & 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<double> & 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)); + } + + + + 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<double> & 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<double> & 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 */, 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)); + } + } + + + + + + + + + + /// 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<double> & 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<double> & 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<const Torus*> (&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; + } + + + +} diff --git a/contrib/Netgen/libsrc/csg/algprim.hpp b/contrib/Netgen/libsrc/csg/algprim.hpp new file mode 100644 index 0000000000..82cd58e788 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/algprim.hpp @@ -0,0 +1,446 @@ +#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 & ist) const; + virtual void Read (istream & ist); + void PrintCoeff (ostream & ost) const; + }; + + + /// A Plane (i.e., the plane and everything behind it). + class Plane : public QuadraticSurface + { + /// 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); + + virtual void GetPrimitiveData (const char *& classname, + Array<double> & coeffs) const; + virtual void SetPrimitiveData (Array<double> & coeffs); + static Primitive * CreateDefault (); + + virtual Primitive * Copy () 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); + + virtual void GetPrimitiveData (const char *& classname, + Array<double> & coeffs) const; + virtual void SetPrimitiveData (Array<double> & 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<double> & coeffs); + + virtual void GetPrimitiveData (const char *& classname, Array<double> & coeffs) const; + virtual void SetPrimitiveData (Array<double> & coeffs); + static Primitive * CreateDefault (); + + virtual Primitive * Copy () 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<double> & coeffs); + + + // static Primitive * CreateDefault (); + virtual void GetPrimitiveData (const char *& classname, Array<double> & coeffs) const; + virtual void SetPrimitiveData (Array<double> & 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 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); + /// + 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); + /// + static Primitive * CreateDefault (); + virtual void GetPrimitiveData (const char *& classname, Array<double> & coeffs) const; + virtual void SetPrimitiveData (Array<double> & 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, double hmax) 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); + /// 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<double> & coeffs) const; + /// OK + virtual void SetPrimitiveData (Array<double> & 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 diff --git a/contrib/Netgen/libsrc/csg/brick.cpp b/contrib/Netgen/libsrc/csg/brick.cpp new file mode 100644 index 0000000000..54c23b1740 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/brick.cpp @@ -0,0 +1,526 @@ +#include <mystdlib.h> + +#include <linalg.hpp> +#include <csg.hpp> + +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<double> & 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<double> & 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<double> 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)); +} +} diff --git a/contrib/Netgen/libsrc/csg/brick.hpp b/contrib/Netgen/libsrc/csg/brick.hpp new file mode 100644 index 0000000000..25b003e0e8 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/brick.hpp @@ -0,0 +1,126 @@ +#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); + virtual ~Parallelogram3d (); + + 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<OneSurfacePrimitive*> faces; + Array<Plane*> faces; + + public: + Brick (Point<3> ap1, Point<3> ap2, Point<3> ap3, Point<3> ap4); + virtual ~Brick (); + 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<double> & coeffs) const; + virtual void SetPrimitiveData (Array<double> & 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); + + virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; + virtual void Reduce (const BoxSphere<3> & box); + }; + +} + +#endif diff --git a/contrib/Netgen/libsrc/csg/bspline2d.cpp b/contrib/Netgen/libsrc/csg/bspline2d.cpp new file mode 100644 index 0000000000..93b5e89621 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/bspline2d.cpp @@ -0,0 +1,242 @@ +#include <mystdlib.h> + +#include <csg.hpp> + +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; +} +} diff --git a/contrib/Netgen/libsrc/csg/csg.hpp b/contrib/Netgen/libsrc/csg/csg.hpp new file mode 100644 index 0000000000..8ddf8d5087 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/csg.hpp @@ -0,0 +1,44 @@ +#ifndef FILE_CSG +#define FILE_CSG + +/* *************************************************************************/ +/* File: geoml.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 21. Jun. 98 */ +/* *************************************************************************/ + +#include <myadt.hpp> +#include <gprim.hpp> +#include <meshing.hpp> + +// #include <geometry2d.hpp> +#include "../gprim/spline.hpp" +#include "../gprim/splinegeometry.hpp" + + + +#include "surface.hpp" +#include "solid.hpp" +#include "identify.hpp" +#include "singularref.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 diff --git a/contrib/Netgen/libsrc/csg/csgeom.cpp b/contrib/Netgen/libsrc/csg/csgeom.cpp new file mode 100644 index 0000000000..ec8125da63 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/csgeom.cpp @@ -0,0 +1,1500 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> + + +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]; + + /* + for (int i = 0; i < solids.Size(); i++) + delete solids[i]->S1(); + for (int i = 0; i < solids.Size(); i++) + delete solids[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<delete_them.Size(); i++) + delete delete_them[i]; + delete_them.DeleteAll(); + surfaces.DeleteAll(); + + for (int i = 0; i < toplevelobjects.Size(); i++) + delete toplevelobjects[i]; + toplevelobjects.DeleteAll (); + for (int i = 0; i < triapprox.Size(); i++) + delete triapprox[i]; + triapprox.DeleteAll(); + + for(int i = 0; i < identifications.Size(); i++) + delete identifications[i]; + identifications.DeleteAll(); + + for (int i = 0; i < singfaces.Size(); i++) + delete singfaces[i]; + singfaces.DeleteAll(); + for (int i = 0; i < singedges.Size(); i++) + delete singedges[i]; + singedges.DeleteAll(); + for (int i = 0; i < singpoints.Size(); i++) + delete singpoints[i]; + singpoints.DeleteAll(); + + changeval++; + } + + + extern int CSGGenerateMesh (CSGeometry & geom, + Mesh *& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend); + + + int CSGeometry :: GenerateMesh (Mesh*& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend) + { + return CSGGenerateMesh (*this, mesh, mparam, perfstepsstart, perfstepsend); + } + + + 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<double> 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 + { + fstream 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<double> 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 :: 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<double> coeffs; + const char * classname; + + out << "csgsurfaces " << GetNSurf() << "\n"; + for(int i=0; i<GetNSurf(); i++) + { + const OneSurfacePrimitive * sp = dynamic_cast< const OneSurfacePrimitive * > (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)); + + + if(sp) + { + sp->GetPrimitiveData(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.Size(); j++) + out << coeffs[j] << " "; + + out << "\n"; + } + } + + void CSGeometry :: LoadSurfaces (istream & in) + { + Array<double> 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<nsurfaces; i++) + { + in >> classname; + in >> size; + + coeffs.SetSize(size); + + for(int j=0; j<size; j++) + in >> 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 == "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 << 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.Get(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.Get(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.Get(name); + else + return NULL; + } + + + + + + const Solid * CSGeometry :: GetSolid (const string & name) const + { + if (solids.Used(name.c_str())) + return solids.Get(name.c_str()); + 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.c_str())) + return splinecurves2d.Get(name.c_str()); + else + return NULL; + } + const SplineGeometry<3> * CSGeometry :: GetSplineCurve3d (const string & name) const + { + if (splinecurves3d.Used(name.c_str())) + return splinecurves3d.Get(name.c_str()); + 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) + { + return toplevelobjects.Append (new TopLevelObject (sol, surf)) - 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.Elem(solidname); + Array<int> 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<char*> & bcname = flags.GetStringListFlag("bcname"); + + Polyhedra * polyh; + if(solid->S1()) + polyh = dynamic_cast<Polyhedra *>(solid->S1()->GetPrimitive()); + else + polyh = dynamic_cast<Polyhedra *>(solid->GetPrimitive()); + + if(polyh) + { + Array < Array<int> * > 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<double> & bcnum = flags.GetNumListFlag("bc"); + + Polyhedra * polyh; + if(solid->S1()) + polyh = dynamic_cast<Polyhedra *>(solid->S1()->GetPrimitive()); + else + polyh = dynamic_cast<Polyhedra *>(solid->GetPrimitive()); + + if(polyh) + { + Array < Array<int> * > 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; + + //(*testout) << "jetzt!" << endl; + for (int i = 0; i < nsurf; i++) + for (int j = i+1; j < nsurf; j++) + { + //(*testout) << "surf" << i << " surf" << j << endl; + if (GetSurface(j) -> IsIdentic (*GetSurface(i), inv, eps)) + { + INDEX_2 i2(i, j); + identicsurfaces.Set (i2, inv); + isidenticto[j] = isidenticto[i]; + //(*testout) << "surfaces " << i2 << " are identic" << endl; + } + } + + (*testout) << "identicmap:" << endl; + for (int i = 0; i < isidenticto.Size(); i++) + (*testout) << i << " -> " << isidenticto[i] << endl; + + /* + for (int i = 0; i < nsurf; i++) + GetSurface(i)->Print (*testout); + */ + } + + + + void CSGeometry :: + GetSurfaceIndices (const Solid * sol, + const BoxSphere<3> & box, + Array<int> & locsurf) const + { + ReducePrimitiveIterator rpi(box); + UnReducePrimitiveIterator urpi; + + ((Solid*)sol) -> IterateSolid (rpi); + sol -> GetSurfaceIndices (locsurf); + ((Solid*)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<int> & 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<int> & 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<int> & 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<int> 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] << ")" <<endl; + //return; + + int pinds[6]; + ArrayMem<int,500> surfused(GetNSurf()); + + ReducePrimitiveIterator rpi(box); + UnReducePrimitiveIterator urpi; + + locsol -> IterateSolid (rpi); + // locsol -> GetSurfaceIndices (lsurfi); + + + // IndexSet iset(GetNSurf()); + locsol -> GetSurfaceIndices (iset); + const Array<int> & 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; + } +} diff --git a/contrib/Netgen/libsrc/csg/csgeom.hpp b/contrib/Netgen/libsrc/csg/csgeom.hpp new file mode 100644 index 0000000000..64badd492c --- /dev/null +++ b/contrib/Netgen/libsrc/csg/csgeom.hpp @@ -0,0 +1,327 @@ +#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 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); + + 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 CSGeometry : public NetgenGeometry + { + private: + /// all surfaces + SYMBOLTABLE<Surface*> surfaces; + + public: + /// primitive of surface + Array<const Primitive*> surf2prim; + + private: + Array<Surface*> delete_them; + + /// all named solids + SYMBOLTABLE<Solid*> solids; + + /// all 2d splinecurves + SYMBOLTABLE< SplineGeometry<2>* > splinecurves2d; + /// all 3d splinecurves + SYMBOLTABLE< SplineGeometry<3>* > splinecurves3d; + + /// all top level objects: solids and surfaces + Array<TopLevelObject*> toplevelobjects; + + /// additional points specified by user + Array<Point<3> > userpoints; + Array<double> userpoints_ref_factor; + + mutable Array<Point<3> > identpoints; + + /// triangular approximation of top level objects + Array<TriangleApproximation*> 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<int> identicsurfaces; + Array<int> isidenticto; + /// identification of boundaries (periodic, thin domains, ...) + + double ideps; + + /// filename of inputfile + string filename; + + public: + CSGeometry (); + CSGeometry (const string & afilename); + virtual ~CSGeometry (); + + void Clean (); + + virtual void Save (string filename) const; + void Save (ostream & ost) const; + void Load (istream & ist); + + void SaveSurfaces (ostream & out) const; + void LoadSurfaces (istream & in); + + virtual void SaveToMeshFile (ostream & ost) const; + + 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<Solid*> & 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 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 (p); userpoints_ref_factor.Append (ref_factor); } + int GetNUserPoints () const + { return userpoints.Size(); } + const Point<3> & 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<SingularFace*> singfaces; + Array<SingularEdge*> singedges; + Array<SingularPoint*> singpoints; + Array<Identification*> 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<int> & locsurf) const; + /// + void GetIndependentSurfaceIndices (const Solid * sol, + const BoxSphere<3> & box, + Array<int> & locsurf) const; + /// + void GetIndependentSurfaceIndices (const Solid * sol, + const Point<3> & p, Vec<3> & v, + Array<int> & locsurf) const; + /// + void GetIndependentSurfaceIndices (Array<int> & 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<BCModification> bcmodifications; + + virtual int GenerateMesh (Mesh*& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend); + + virtual const Refinement & GetRefinement () const; + }; + + + + + +} + +#endif + diff --git a/contrib/Netgen/libsrc/csg/csgparser.cpp b/contrib/Netgen/libsrc/csg/csgparser.cpp new file mode 100644 index 0000000000..c2728bcdf3 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/csgparser.cpp @@ -0,0 +1,1390 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> + + +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_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_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<int> 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; i<pnums.Size(); i++) + if(!cleaned_pnums.Contains(pnums[i])) + cleaned_pnums.Append(pnums[i]); + + if(cleaned_pnums.Size() == 3) + { + polyhedron->AddFace(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; i<pnums.Size(); i++) + msg << " " << pnums[i]; + throw NgException(msg.str()); + } + + + + if (scan.GetToken() == ')') + { + scan.ReadNext(); + break; + } + scan.ReadNext(); + inputface++; + } + + geom->AddSurfaces (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<Solid*> (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 <int D> + void LoadSpline (SplineGeometry<D> & spline, CSGScanner & scan) + { + double hd; + Point<D> x; + int nump, numseg; + + //scan.ReadNext(); + scan >> nump >> ';'; + + hd = 1; + spline.geompoints.SetSize(nump); + for(int i = 0; i<nump; i++) + { + if(D==2) + scan >> x(0) >> ',' >> x(1) >> ';'; + else if(D==3) + scan >> x(0) >> ',' >> x(1) >> ',' >> x(2) >> ';'; + + spline.geompoints[i] = GeomPoint<D>(x,hd); + } + + scan >> numseg;// >> ';'; + + spline.splines.SetSize(numseg); + + int pnums,pnum1,pnum2,pnum3; + + + for(int i = 0; i<numseg; i++) + { + scan >> ';' >> pnums >> ','; + if (pnums == 2) + { + scan >> pnum1 >> ',' >> pnum2;// >> ';'; + spline.splines[i] = new LineSeg<D>(spline.geompoints[pnum1-1], + spline.geompoints[pnum2-1]); + } + else if (pnums == 3) + { + scan >> pnum1 >> ',' >> pnum2 >> ',' + >> pnum3;// >> ';'; + spline.splines[i] = new SplineSeg3<D>(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<D>(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<double> 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<char*> 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; i<vals.Size(); i++) + delete [] vals[i]; + } + } + else if (scan.GetToken() == TOK_NUM) + { + flags.SetFlag (name.c_str(), scan.GetNumValue()); + scan.ReadNext(); + } + } + else + { + flags.SetFlag (name.c_str()); + } + } + } + + + /* + Main parsing function for CSG geometry + */ + CSGeometry * ParseCSG (istream & istr) + { + CSGScanner scan(istr); + + geom = new CSGeometry; + + scan.ReadNext(); + if (scan.GetToken() != TOK_RECO) // keyword 'algebraic3d' + return 0; + + scan.ReadNext(); + + try + { + while (1) + { + if (scan.GetToken() == TOK_END) break; + + if (scan.GetToken() == TOK_SOLID) + { + scan.ReadNext(); + if (scan.GetToken() != TOK_STRING) + scan.Error ("name identifier expected"); + string solidname = scan.GetStringValue(); + + scan.ReadNext(); + + ParseChar (scan, '='); + Solid * solid = ParseSolid (scan); + + Flags flags; + ParseFlags (scan, flags); + + geom->SetSolid (solidname.c_str(), new Solid (Solid::ROOT, solid)); + geom->SetFlags (solidname.c_str(), flags); + + ParseChar (scan, ';'); + + PrintMessage (4, "define solid ", solidname); + } + + else if (scan.GetToken() == TOK_TLO) + + { // a TopLevelObject definition + + scan.ReadNext(); + + string name = scan.GetStringValue(); + scan.ReadNext(); + + if (scan.GetToken() != TOK_STRING) + + { // a solid TLO + + Flags flags; + ParseFlags (scan, flags); + + ParseChar (scan, ';'); + if (!geom->GetSolid (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<double> & 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<int> 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<double> & 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<int> 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<int> 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<int> 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<int> 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); + */ + } + + +}; + diff --git a/contrib/Netgen/libsrc/csg/csgparser.hpp b/contrib/Netgen/libsrc/csg/csgparser.hpp new file mode 100644 index 0000000000..dfbd24ac04 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/csgparser.hpp @@ -0,0 +1,101 @@ +#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_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 + diff --git a/contrib/Netgen/libsrc/csg/csgpkg.cpp b/contrib/Netgen/libsrc/csg/csgpkg.cpp new file mode 100644 index 0000000000..6ce6bf1a4e --- /dev/null +++ b/contrib/Netgen/libsrc/csg/csgpkg.cpp @@ -0,0 +1,700 @@ +#include <mystdlib.h> +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> + + +#include <incvis.hpp> +#include <visual.hpp> + + +#include "vscsg.hpp" + + +extern "C" int Ng_CSG_Init (Tcl_Interp * interp); + + + +namespace netgen +{ + extern DLL_HEADER NetgenGeometry * ng_geometry; + extern DLL_HEADER AutoPtr<Mesh> mesh; + + static VisualSceneGeometry vsgeom; + + char * err_needscsgeometry = (char*) "This operation needs an CSG geometry"; + extern char * err_needsmesh; + extern char * err_jobrunning; + + + + + int Ng_ParseGeometry (ClientData clientData, + Tcl_Interp * interp, + int argc, tcl_const char *argv[]) + { + CSGeometry * csgeom = dynamic_cast<CSGeometry*> (ng_geometry); + 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<CSGeometry*> (ng_geometry); + + + 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<CSGeometry*> (ng_geometry); + 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<CSGeometry*> (ng_geometry); + 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<double> 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<CSGeometry*> (ng_geometry); + 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<CSGeometry*> (ng_geometry); + 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<double> 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<CSGeometry*> (ng_geometry); + 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<CSGeometry*> (ng_geometry); + 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<CSGeometry*> (ng_geometry); + 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<CSGeometry*> (ng_geometry); + 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<CSGeometry*> (ng_geometry); + 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<CSGeometry*> (ng_geometry); + if (!geometry) + { + Tcl_SetResult (interp, err_needscsgeometry, TCL_STATIC); + return TCL_ERROR; + } + + if (!mesh.Ptr()) + { + 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, globh); + return TCL_OK; + } + + + int Ng_SingularPointMS (ClientData clientData, + Tcl_Interp * interp, + int argc, tcl_const char *argv[]) + { + CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry); + 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, 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<CSGeometry*> (ng_geometry); + if (geometry) + { + vsgeom.SetGeometry (geometry); + return &vsgeom; + } + return NULL; + } + + +} + + +using namespace netgen; + +int Ng_CSG_Init (Tcl_Interp * interp) +{ + geometryregister.Append (new CSGeometryRegister); + + + + 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; +} + + + diff --git a/contrib/Netgen/libsrc/csg/curve2d.cpp b/contrib/Netgen/libsrc/csg/curve2d.cpp new file mode 100644 index 0000000000..7091e87af9 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/curve2d.cpp @@ -0,0 +1,78 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <csg.hpp> + +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(); +} +} diff --git a/contrib/Netgen/libsrc/csg/curve2d.hpp b/contrib/Netgen/libsrc/csg/curve2d.hpp new file mode 100644 index 0000000000..066a40adb7 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/curve2d.hpp @@ -0,0 +1,67 @@ +#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 diff --git a/contrib/Netgen/libsrc/csg/edgeflw.cpp b/contrib/Netgen/libsrc/csg/edgeflw.cpp new file mode 100644 index 0000000000..c9c5c1667c --- /dev/null +++ b/contrib/Netgen/libsrc/csg/edgeflw.cpp @@ -0,0 +1,1850 @@ +#include <mystdlib.h> +#include <meshing.hpp> +#include <csg.hpp> + +// #undef DEVELOP +// #define DEVELOP + +namespace netgen +{ + + EdgeCalculation :: + EdgeCalculation (const CSGeometry & ageometry, + Array<SpecialPoint> & aspecpoints) + : geometry(ageometry), specpoints(aspecpoints) + { + 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 (int i = 1; i <= mesh.GetNP(); i++) + meshpoint_tree->Insert (mesh.Point(i), i); + + + // add all special points before edge points (important for periodic identification) + // JS, Jan 2007 + const double di=1e-7*geometry.MaxSize(); + Array<int> 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<int> hsp(specpoints.Size()); + Array<int> glob2hsp(specpoints.Size()); + Array<int> startpoints, endpoints; + + + int pos, ep; + int layer; + + Point<3> p, np; + int pi1, s1, s2, s1_orig, s2_orig; + + Array<Point<3> > edgepoints; + Array<double> curvelength; + int copyedge = 0, copyfromedge = -1, copyedgeidentification = -1; + + Array<int> 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<hsp.Size(); i++) + // (*testout) << "hsp["<<i<<"] ... " << specpoints[hsp[i]].p << endl; + + + cntedge = 0; + INDEX_2_HASHTABLE<int> identification_used(100); // identification i already used for startpoint j + + mesh.GetIdentifications().Delete(); + + TABLE<int> 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<int> 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 " <<specpoints[i].v <<" is in " << tlo->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<Segment> refedges; + Array<bool> 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); + } + + + /* + // 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<hsp.Size(); i++) +// { +// (*testout) << "pos2 hsp["<<i<<"] ... " << specpoints[hsp[i]].p << endl; +// } + } + } + + + + + + + /* + If two or more edges share the same initial and end-points, + then they need at least two segments + */ + void EdgeCalculation :: + SplitEqualOneSegEdges (Mesh & mesh) + { + // int i, j; + SegmentIndex si; + PointIndex pi; + + Array<int> osedges(cntedge); + INDEX_2_HASHTABLE<int> 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(i2.I1()) << " - " << mesh.Point(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++) + { + 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<int> & hsp, + double h, const Mesh & mesh, + Array<Point<3> > & edgepoints, + Array<double> & curvelength) + { + int s1, s2, s1_rep, s2_rep; + double len, steplen, cursteplen, loch; + Point<3> p, np, pnp; + Vec<3> a1, a2, t; + + Array<int> 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, h), + geometry.GetSurface(s2) -> LocH (p, 3, 1, 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, h), + geometry.GetSurface(s2_rep) -> LocH (np, 3, 1, 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<Point<3> > & edgepoints, + Array<Segment> & refedges, + Array<bool> & refedgesinv) + { + Segment seg; + Array<int> locsurfind, locsurfind2; + + Array<int> 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<bool> 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; + hi = refedges.Append (seg); + 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; + + 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<refedges.Size()-1; i++) + { + for(int j=i+1; !todelete.Test(i) && j<refedges.Size(); j++) + { + if(todelete.Test(j)) + continue; + + if(refedges[i].si == refedges[j].si && + refedges[i].domin == refedges[j].domin && + refedges[i].domout == refedges[j].domout && + geometry.GetSurfaceClassRepresentant(refedges[i].surfnr1) == geometry.GetSurfaceClassRepresentant(refedges[j].surfnr1) && + geometry.GetSurfaceClassRepresentant(refedges[i].surfnr2) == geometry.GetSurfaceClassRepresentant(refedges[j].surfnr2) + // && refedgesinv[i] == refedgesinv[j] // JS, 20060802 + ) + { + if(debug) + (*testout) << "equal segments: " << refedges[i] << " pri " << edges_priority[i] + << " tlosurf " << refedges[i].tlosurf + << "\n and " << refedges[j] << " pri " << edges_priority[j] + << " tlosurf " << refedges[i].tlosurf << endl; + + if(edges_priority[i] < 10 && edges_priority[i] < edges_priority[j]) + { + todelete.Set(i); + } + else if (edges_priority[j] < 10 && edges_priority[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<Segment> & refedges, + const Array<bool> & refedgesinv, + const Array<Point<3> > & edgepoints, + const Array<double> & 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<int> 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<Segment> & refedges, + const Array<bool> & refedgesinv, + const Array<Point<3> > & edgepoints, + const Array<double> & 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<Segment> & refedges, + const Array<bool> & 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 i, j; + int nsol; + int nsurf = geometry.GetNSurf(); + int layer(0); + + BitArray pointatsurface (nsurf); + Point<3> p1, p2; + Vec<3> nv, tv; + Solid * tansol; + Array<int> tansurfind; + // const Solid * sol; + + double size = geometry.MaxSize(); + nsol = geometry.GetNTopLevelObjects(); + + + pointatsurface.Clear(); + + /* + for (i = 1; i <= specpoints.Size(); i++) + { + int classrep; + + classrep = geometry.GetSurfaceClassRepresentant (specpoints[i].s1); + pointatsurface.Set (classrep); + classrep = geometry.GetSurfaceClassRepresentant (specpoints[i].s2); + pointatsurface.Set (classrep); + // pointatsurface.Set (specpoints[i].s1); + // pointatsurface.Set (specpoints[i].s2); + } + */ + for (i = 1; i <= mesh.GetNSeg(); i++) + { + const Segment & seg = mesh.LineSegment(i); + int classrep; + +#ifdef DEVELOP + (*testout) << seg.surfnr1 << ", " << seg.surfnr2 << ", si = " << seg.si << endl; +#endif + classrep = geometry.GetSurfaceClassRepresentant (seg.si); + + pointatsurface.Set (classrep); + } + + + for (i = 0; i < nsurf; i++) + { + int classrep = geometry.GetSurfaceClassRepresentant (i); + + if (!pointatsurface.Test(classrep)) + { + const Surface * s = geometry.GetSurface(i); + p1 = s -> GetSurfacePoint(); + nv = s -> GetNormalVector (p1); + + double hloc = + min2 (s->LocH (p1, 3, 1, h), mesh.GetH(p1)); + + tv = nv.GetNormal (); + tv *= (hloc / tv.Length()); + p2 = p1 + tv; + s->Project (p2); + + + 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 (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) + { + if (!tansol->VectorIn(p1, nv)) + { + seg1.domin = j; + seg2.domin = j; + seg1.tlosurf = j; + seg2.tlosurf = j; + } + else + { + seg1.domout = j; + seg2.domout = j; + seg1.tlosurf = j; + seg2.tlosurf = j; + } + // seg.s2 = i; + // seg.invs1 = surfaces[i] -> Inverse(); + // seg.invs2 = ! (surfaces[i] -> Inverse()); + } + delete tansol; + } + } + + + 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 + } + } + } + } + +} diff --git a/contrib/Netgen/libsrc/csg/edgeflw.hpp b/contrib/Netgen/libsrc/csg/edgeflw.hpp new file mode 100644 index 0000000000..4c2fc9495a --- /dev/null +++ b/contrib/Netgen/libsrc/csg/edgeflw.hpp @@ -0,0 +1,110 @@ +#ifndef FILE_EDGEFLW +#define FILE_EDGEFLW + +/**************************************************************************/ +/* File: edgeflw.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Okt. 95 */ +/**************************************************************************/ + +namespace netgen +{ + + + + /* + + Edge - following function and + Projection to edge of implicitly given edge + + */ + + + /** + Calculates edges. + The edges of a solid geometry are computed. Special + points have to be given. + */ + extern void CalcEdges (const CSGeometry & geometry, + const Array<SpecialPoint> & specpoints, + double h, Mesh & mesh); + + + + + + class EdgeCalculation + { + const CSGeometry & geometry; + Array<SpecialPoint> & specpoints; + Point3dTree * searchtree; + Point3dTree * meshpoint_tree; + int cntedge; + + double ideps; + + public: + EdgeCalculation (const CSGeometry & ageometry, + Array<SpecialPoint> & aspecpoints); + + ~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<SpecialPoint> & hsp, + const Array<int> & hsp, + double h, const Mesh & mesh, + Array<Point<3> > & edgepoints, + Array<double> & curvelength); + + + void AnalyzeEdge (int s1, int s2, int s1_rep, int s2_rep, int pos, int layer, + const Array<Point<3> > & edgepoints, + Array<Segment> & refedges, + Array<bool> & refedgesinv); + + void StoreEdge (const Array<Segment> & refedges, + const Array<bool> & refedgesinv, + const Array<Point<3> > & edgepoints, + const Array<double> & curvelength, + int layer, + Mesh & mesh); + + void StoreShortEdge (const Array<Segment> & refedges, + const Array<bool> & refedgesinv, + const Array<Point<3> > & edgepoints, + const Array<double> & curvelength, + int layer, + Mesh & mesh); + + void CopyEdge (const Array<Segment> & refedges, + const Array<bool> & 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 diff --git a/contrib/Netgen/libsrc/csg/explicitcurve2d.cpp b/contrib/Netgen/libsrc/csg/explicitcurve2d.cpp new file mode 100644 index 0000000000..81c0e7ac55 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/explicitcurve2d.cpp @@ -0,0 +1,160 @@ +#include <mystdlib.h> +#include <csg.hpp> + +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; + } + +} diff --git a/contrib/Netgen/libsrc/csg/explicitcurve2d.hpp b/contrib/Netgen/libsrc/csg/explicitcurve2d.hpp new file mode 100644 index 0000000000..559030b254 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/explicitcurve2d.hpp @@ -0,0 +1,113 @@ +#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<Point<2> > points; + /// + Array<int> 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 diff --git a/contrib/Netgen/libsrc/csg/extrusion.cpp b/contrib/Netgen/libsrc/csg/extrusion.cpp new file mode 100644 index 0000000000..29676395f8 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/extrusion.cpp @@ -0,0 +1,876 @@ +#include <mystdlib.h> + +#include <linalg.hpp> +#include <csg.hpp> + + +namespace netgen +{ + + Array<Point<3> > 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; i<path->GetNSplines(); 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<double> & raw_data) + { + deletable = true; + + int pos=0; + + Array< Point<2> > p(3); + + int ptype = int(raw_data[pos]); pos++; + + for(int i=0; i<ptype; i++) + { + p[i](0) = raw_data[pos]; pos++; + p[i](1) = raw_data[pos]; pos++; + } + if(ptype == 2) + { + profile = new LineSeg<2>(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<const ExtrusionFace*>(&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<double> 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; i<path->GetNSplines(); i++) + { + if(mindist[i] > cutdist) 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; i<path->GetNSplines(); 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<ips.Size(); i++) + { + //(*testout) << " ip " << ips[i]; + + double t = (ips[i](comp)-p2d(comp))/v2d(comp); + + if(t < -eps) + before++; + else if(t > 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<double> & 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; j<profile.GetNSplines(); 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<faces.Size(); i++) + delete faces[i]; + } + + + + + + INSOLID_TYPE Extrusion :: BoxInSolid (const BoxSphere<3> & box) const + { + for(int i=0; i<faces.Size(); i++) + { + if(faces[i]->BoxIntersectsFace(box)) + return DOES_INTERSECT; + } + + return PointInSolid(box.Center(),0); + } + + + INSOLID_TYPE Extrusion :: PointInSolid (const Point<3> & p, + const double eps, + Array<int> * 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; i<faces.Size(); i++) + { + faces[i]->LineIntersections(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<int> 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; + } + + +} diff --git a/contrib/Netgen/libsrc/csg/extrusion.hpp b/contrib/Netgen/libsrc/csg/extrusion.hpp new file mode 100644 index 0000000000..189639bd2e --- /dev/null +++ b/contrib/Netgen/libsrc/csg/extrusion.hpp @@ -0,0 +1,155 @@ +#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<double> & raw_data); + + + ~ExtrusionFace(); + + 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<double> & 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; + + const Vec<3> & z_direction; + + Array<ExtrusionFace*> faces; + + mutable int latestfacenum; + + public: + Extrusion(const SplineGeometry<3> & path_in, + const SplineGeometry<2> & profile_in, + const Vec<3> & z_dir); + ~Extrusion(); + 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<int> * 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 diff --git a/contrib/Netgen/libsrc/csg/gencyl.cpp b/contrib/Netgen/libsrc/csg/gencyl.cpp new file mode 100644 index 0000000000..1305c1b87b --- /dev/null +++ b/contrib/Netgen/libsrc/csg/gencyl.cpp @@ -0,0 +1,179 @@ +#include <linalg.hpp> +#include <csg.hpp> + + +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); + } + +} diff --git a/contrib/Netgen/libsrc/csg/gencyl.hpp b/contrib/Netgen/libsrc/csg/gencyl.hpp new file mode 100644 index 0000000000..e5db270dec --- /dev/null +++ b/contrib/Netgen/libsrc/csg/gencyl.hpp @@ -0,0 +1,70 @@ +#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 diff --git a/contrib/Netgen/libsrc/csg/genmesh.cpp b/contrib/Netgen/libsrc/csg/genmesh.cpp new file mode 100644 index 0000000000..5e891639b8 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/genmesh.cpp @@ -0,0 +1,849 @@ +#include <mystdlib.h> + + +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + + +namespace netgen +{ + Array<SpecialPoint> specpoints; + static Array<MeshPoint> 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"; + + for (int i = 0; i < geom.GetNUserPoints(); i++) + { + mesh.AddPoint(geom.GetUserPoint (i)); + mesh.Points().Last().Singularity (geom.GetUserPointRefFactor(i)); + mesh.AddLockedPoint (PointIndex (i+1)); + } + + 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, const bool setmeshsize = false) + { + EdgeCalculation ec (geom, specpoints); + 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; + } + + 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); + Box3dTree 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<int> 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) + { + const char * savetask = multithread.task; + multithread.task = "Surface meshing"; + + Array<Segment> segments; + int noldp = mesh.GetNP(); + + double starttime = GetTime(); + + // find master faces from identified + Array<int> masterface(mesh.GetNFD()); + for (int i = 1; i <= mesh.GetNFD(); i++) + masterface.Elem(i) = i; + + Array<INDEX_2> 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<geom.bcmodifications.Size(); k++) + { + delete geom.bcmodifications[k].bcname; + geom.bcmodifications[k].bcname = NULL; + } + + //!! + + + for (int j = 0; j < geom.singfaces.Size(); j++) + { + Array<int> 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 " <<mesh[mesh[si][1]]<< endl; + } + + (*testout) << "num-segments " << segments.Size() << endl; + + for (int i = 1; i <= geom.identifications.Size(); i++) + { + geom.identifications.Get(i)-> + 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"); + + extern void Render(); + 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"); + } + + extern void Render(); + Render(); + } + while (changed); + + + mesh.SplitSeparatedFaces(); + mesh.CalcSurfacesOfNode(); + + multithread.task = savetask; + } + + + + int CSGGenerateMesh (CSGeometry & geom, + Mesh *& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend) + { + if (mesh && mesh->GetNSE() && + !geom.GetNSolids()) + { + if (perfstepsstart < MESHCONST_MESHVOLUME) + perfstepsstart = MESHCONST_MESHVOLUME; + } + + if (perfstepsstart <= MESHCONST_ANALYSE) + { + if (mesh) + mesh -> DeleteMesh(); + else + mesh = new Mesh(); + + mesh->SetGlobalH (mparam.maxh); + mesh->SetMinimalH (mparam.minh); + + Array<double> 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); + } + + 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 || perfstepsend <= MESHCONST_ANALYSE) + return TCL_OK; + + + if (perfstepsstart <= MESHCONST_MESHEDGES) + { + FindEdges (geom, *mesh, 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, true); + if (multithread.terminate) return TCL_OK; + + mesh->DeleteMesh(); + + FindPoints (geom, *mesh); + if (multithread.terminate) return TCL_OK; + FindEdges (geom, *mesh); + if (multithread.terminate) return TCL_OK; + } + } + + if (multithread.terminate || perfstepsend <= MESHCONST_MESHEDGES) + return TCL_OK; + + + if (perfstepsstart <= MESHCONST_MESHSURFACE) + { + MeshSurface (geom, *mesh); + 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 && 0) + { + mesh->CalcLocalH(mparam.grading); + mesh->DeleteMesh(); + + FindPoints (geom, *mesh); + if (multithread.terminate) return TCL_OK; + FindEdges (geom, *mesh); + if (multithread.terminate) return TCL_OK; + + MeshSurface (geom, *mesh); + 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 || perfstepsend <= MESHCONST_OPTSURFACE) + return TCL_OK; + + + if (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 || perfstepsend <= MESHCONST_MESHVOLUME) + return TCL_OK; + + + if (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 + } + + return TCL_OK; + } +} diff --git a/contrib/Netgen/libsrc/csg/geoml.hpp b/contrib/Netgen/libsrc/csg/geoml.hpp new file mode 100644 index 0000000000..e7974ad206 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/geoml.hpp @@ -0,0 +1,16 @@ +#ifndef FILE_GEOML +#define FILE_GEOML + +/* *************************************************************************/ +/* File: geoml.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 21. Jun. 98 */ +/* *************************************************************************/ + +#include <geom/geom.hh> + +#include <geom/solid.hh> +#include <geom/algprim.hh> +#include <geom/adtree.hh> +#include <geom/csgeom.hh> +#endif diff --git a/contrib/Netgen/libsrc/csg/identify.cpp b/contrib/Netgen/libsrc/csg/identify.cpp new file mode 100644 index 0000000000..e3086a3bad --- /dev/null +++ b/contrib/Netgen/libsrc/csg/identify.cpp @@ -0,0 +1,1662 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + + +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<class SpecialPoint> & points) +{ + ; +} +*/ + + +int Identification :: +Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2, + const TABLE<int> & specpoint2solid, + const TABLE<int> & 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<Segment> & segs, + Mesh & mesh, const Surface * surf) +{ + cout << "Identification::BuildSurfaceElements called for base-class" << endl; + ; +} + + +void Identification :: +BuildVolumeElements (Array<class Element2d> & surfels, + class Mesh & mesh) +{ + ; +} + +void Identification :: +GetIdentifiedFaces (Array<INDEX_2> & 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) + : Identification(anr, ageom) +{ + s1 = as1; + s2 = as2; +} + +PeriodicIdentification :: ~PeriodicIdentification () +{ + ; +} + +/* +void PeriodicIdentification :: IdentifySpecialPoints +(Array<class SpecialPoint> & 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<int> & specpoint2solid, + const TABLE<int> & specpoint2surface) const +{ + int i; + double val; + + SpecialPoint hsp1 = sp1; + SpecialPoint hsp2 = sp2; + + for (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; + + + 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-6) + return 1; + } + + return 0; +} + +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); + + if (s1->PointOnSurface (p)) + { + snew = s2; + } + else + { + if (s2->PointOnSurface (p)) + { + snew = s1; + } + else + { + cerr << "GetIdenfifiedPoint: Not possible" << endl; + exit (1); + } + } + + // project to other surface + Point<3> hp = p; + 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) +{ + int i, j; + for (i = 1; i <= mesh.GetNP(); i++) + { + Point<3> p = mesh.Point(i); + if (s1->PointOnSurface (p)) + { + Point<3> pp = p; + s2->Project (pp); + for (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<Segment> & 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<int> 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; i<slices.Size(); i++) + if((i==0 && slices[i] <= 0) || + (i>0 && 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<class SpecialPoint> & 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<int> & specpoint2solid, + const TABLE<int> & specpoint2surface) const +{ + //(*testout) << "identcheck: " << sp1.p << "; " << sp2.p << endl; + + if (!dom_surf_valid) + { + const_cast<bool&> (dom_surf_valid) = 1; + Array<int> & hsurf = const_cast<Array<int>&> (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<int,PointIndex::BASE> 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<int> points_on_surf2; + + for (int i2 = 1; i2 <= np; i2++) + if (s2->PointOnSurface (mesh.Point(i2))) + points_on_surf2.Append (i2); + + Array<int> 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<int> segs_on_face1, segs_on_face2; + + identfaces.DeleteData(); + + //(*testout) << "identify faces, nr = " << nr << endl; + + for (int i = 1; i <= mesh.GetNFD(); 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++) + { + int surfj = mesh.GetFaceDescriptor(j).SurfNr(); + + if (surfi == surfj) continue; + if (s2rep != surfj) 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<Segment> & segs, + Mesh & mesh, const Surface * surf) +{ + bool found = 0; + int cntquads = 0; + + Array<int,PointIndex::BASE> 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<bool> 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))) + { + Element2d el(s1[0], s1[1], s2[0], s2[1]); + + Vec<3> n = Cross (mesh[el[1]] - mesh[el[0]], + mesh[el[3]] - mesh[el[0]]); + + Vec<3> ns = surf->GetNormalVector (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<Segment> aux; + //for(int i=0; i<segs.Size();i++) + // if(!foundseg[i]) + // aux.Append(segs[i]); + segs.SetSize(0); + } + else + { + BuildSurfaceElements2 (segs, mesh, surf); + } +} + + + + + + +void CloseSurfaceIdentification :: +BuildSurfaceElements2 (Array<Segment> & 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<int>::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<class Element2d> & 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<class SpecialPoint> & 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<int> & specpoint2solid, + const TABLE<int> & 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<Segment> & 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); +} + +} + diff --git a/contrib/Netgen/libsrc/csg/identify.hpp b/contrib/Netgen/libsrc/csg/identify.hpp new file mode 100644 index 0000000000..ef3f75564c --- /dev/null +++ b/contrib/Netgen/libsrc/csg/identify.hpp @@ -0,0 +1,210 @@ + +#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<int> 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<class SpecialPoint> & points); + + /// can identify both special points (fixed direction) + /// (identified points, same tangent) + virtual int Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2, + const TABLE<int> & specpoint2solid, + const TABLE<int> & 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<class Segment> & segs, + class Mesh & mesh, + const Surface * surf); + + /// insert volume elements in thin layers + virtual void BuildVolumeElements (Array<class Element2d> & surfels, + class Mesh & mesh); + + /// get list of identified faces + virtual void GetIdentifiedFaces (Array<INDEX_2> & idfaces) const; + + friend ostream & operator<< (ostream & ost, Identification & ident); + }; + + + class PeriodicIdentification : public Identification + { + const Surface * s1; + const Surface * s2; + public: + PeriodicIdentification (int anr, + const CSGeometry & ageom, + const Surface * as1, + const Surface * as2); + virtual ~PeriodicIdentification (); + virtual void Print (ostream & ost) const; + virtual void GetData (ostream & ost) const; + + + // virtual void IdentifySpecialPoints (Array<class SpecialPoint> & points); + virtual int Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2, + const TABLE<int> & specpoint2solid, + const TABLE<int> & specpoint2surface) const; + + virtual int Identifyable (const Point<3> & p1, const Point<3> & sp2) const; + virtual int GetIdentifiedPoint (class Mesh & mesh, int pi1); + virtual void IdentifyPoints (class Mesh & mesh); + virtual void IdentifyFaces (class Mesh & mesh); + virtual void BuildSurfaceElements (Array<class Segment> & segs, + class Mesh & mesh, + const Surface * surf); + }; + + + /// + 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<double> slices; + /// used only for domain-local identification: + Array<int> 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<class SpecialPoint> & points); + virtual int Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2, + const TABLE<int> & specpoint2solid, + const TABLE<int> & 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<double> & GetSlices () const { return slices; } + virtual void IdentifyPoints (class Mesh & mesh); + virtual void IdentifyFaces (class Mesh & mesh); + virtual void BuildSurfaceElements (Array<class Segment> & segs, + class Mesh & mesh, + const Surface * surf); + void BuildSurfaceElements2 (Array<class Segment> & segs, + class Mesh & mesh, + const Surface * surf); + + virtual void BuildVolumeElements (Array<class Element2d> & 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<class SpecialPoint> & points); + virtual int Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2, + const TABLE<int> & specpoint2solid, + const TABLE<int> & specpoint2surface) const; + + + virtual void IdentifyPoints (class Mesh & mesh); + virtual void BuildSurfaceElements (Array<class Segment> & segs, + class Mesh & mesh, + const Surface * surf); + }; + +} + +#endif diff --git a/contrib/Netgen/libsrc/csg/manifold.cpp b/contrib/Netgen/libsrc/csg/manifold.cpp new file mode 100644 index 0000000000..9733389d67 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/manifold.cpp @@ -0,0 +1,14 @@ +#include <csg.hpp> + +namespace netgen +{ +Manifold :: Manifold () +{ + ; +} + +Manifold :: ~Manifold () +{ + ; +} +} diff --git a/contrib/Netgen/libsrc/csg/manifold.hpp b/contrib/Netgen/libsrc/csg/manifold.hpp new file mode 100644 index 0000000000..cc60e955e0 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/manifold.hpp @@ -0,0 +1,29 @@ +#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 diff --git a/contrib/Netgen/libsrc/csg/meshsurf.cpp b/contrib/Netgen/libsrc/csg/meshsurf.cpp new file mode 100644 index 0000000000..19e12eb226 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/meshsurf.cpp @@ -0,0 +1,211 @@ +#include <mystdlib.h> + +#include <csg.hpp> +#include <meshing.hpp> + + + +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) +{ + ; +} + + +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, 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: Intializing 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); + +} + + +} diff --git a/contrib/Netgen/libsrc/csg/meshsurf.hpp b/contrib/Netgen/libsrc/csg/meshsurf.hpp new file mode 100644 index 0000000000..e6c6922555 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/meshsurf.hpp @@ -0,0 +1,97 @@ +#ifndef FILE_MESHSURF +#define FILE_MESHSURF + +namespace netgen +{ + + /// + class Meshing2Surfaces : public Meshing2 + { + /// + const Surface & surface; + + 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; + /// + virtual void ProjectPoint2 (INDEX surfind, INDEX surfind2, Point<3> & p) const; + /// + virtual void GetNormalVector(INDEX surfind, const Point<3> & p, Vec<3> & n) const; + }; + + + + 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; + + 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; + + virtual void ProjectToEdge (Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & egi) const; + + }; + +} + +#endif + diff --git a/contrib/Netgen/libsrc/csg/polyhedra.cpp b/contrib/Netgen/libsrc/csg/polyhedra.cpp new file mode 100644 index 0000000000..6d96d7b437 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/polyhedra.cpp @@ -0,0 +1,738 @@ +#include <mystdlib.h> + +#include <linalg.hpp> +#include <csg.hpp> + +namespace netgen +{ + +Polyhedra::Face::Face (int pi1, int pi2, int pi3, + const Array<Point<3> > & 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<int> & 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<int> 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<point_on_faces.Size(); i++) + { + for(int j=0; j<3; j++) + { + double dist = Dist(p,points[faces[point_on_faces[i]].pnums[j]]); + if(dist > 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 = " <<res <<endl; + + if(res != DOES_INTERSECT) + return res; + + int point_on_n_faces = 0; + + Vec<3> v1n = v1; + v1n.Normalize(); + Vec<3> v2n = v2 - (v2 * v1n) * v1n; + v2n.Normalize(); + + double cosv2, cosv2max = -1; + + + 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<int> & 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<double> & 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<double> & /* 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); + + return points.Append (p); +} + +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<int> * > & polysurfs) +{ + int maxnum = -1; + + for(int i = 0; i<faces.Size(); i++) + { + if(faces[i].inputnr > maxnum) + maxnum = faces[i].inputnr; + } + + polysurfs.SetSize(maxnum+1); + for(int i=0; i<polysurfs.Size(); i++) + polysurfs[i] = new Array<int>; + + for(int i = 0; i<faces.Size(); i++) + polysurfs[faces[i].inputnr]->Append(faces[i].planenr); +} + + +void Polyhedra::CalcSpecialPoints (Array<Point<3> > & pts) const +{ + for (int i = 0; i < points.Size(); i++) + pts.Append (points[i]); +} + + +void Polyhedra :: AnalyzeSpecialPoint (const Point<3> & /* pt */, + Array<Point<3> > & /* 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); +} + + +} + + diff --git a/contrib/Netgen/libsrc/csg/polyhedra.hpp b/contrib/Netgen/libsrc/csg/polyhedra.hpp new file mode 100644 index 0000000000..0a78504256 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/polyhedra.hpp @@ -0,0 +1,104 @@ +#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<Point<3> > & points, + int ainputnr); + }; + + Array<Point<3> > points; + Array<Face> faces; + Array<Plane*> 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<int> & surfind, double eps) const; + + + virtual void GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, + Array<int> & surfind, double eps) const; + + virtual void CalcSpecialPoints (Array<Point<3> > & pts) const; + virtual void AnalyzeSpecialPoint (const Point<3> & pt, + Array<Point<3> > & 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<double> & coeffs) const; + virtual void SetPrimitiveData (Array<double> & 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<int> * > & polysurfs); + + protected: + int FaceBoxIntersection (int fnr, const BoxSphere<3> & box) const; + // void CalcData(); + }; + +} + +#endif diff --git a/contrib/Netgen/libsrc/csg/revolution.cpp b/contrib/Netgen/libsrc/csg/revolution.cpp new file mode 100644 index 0000000000..89863b6dd0 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/revolution.cpp @@ -0,0 +1,900 @@ +#include <mystdlib.h> + +#include <linalg.hpp> +#include <csg.hpp> + +namespace netgen +{ + void RevolutionFace :: Init(void) + { + const LineSeg<2> * line = dynamic_cast<const LineSeg<2>*>(spline); + const SplineSeg3<2> * spline3 = dynamic_cast<const SplineSeg3<2>*>(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_vec.Size(); i++) + { + checklines_normal.Append(new Vec<2>); + (*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<double> & raw_data) + { + deletable = true; + + int pos = 0; + + Array< Point<2> > p(3); + + int stype = int(raw_data[pos]); pos++; + + for(int i=0; i<stype; i++) + { + p[i](0) = raw_data[pos]; pos++; + p[i](1) = raw_data[pos]; pos++; + } + + if(stype == 2) + { + spline = new LineSeg<2>(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<checklines_start.Size(); i++) + { + delete checklines_start[i]; + delete checklines_vec[i]; + delete checklines_normal[i]; + } + + if(deletable) + delete spline; + } + + void RevolutionFace :: CalcProj(const Point<3> & 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<const RevolutionFace*>(&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); + + Point<2> p; + CalcProj(point,p); + + return 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); + } + + void RevolutionFace :: CalcGradient (const Point<3> & point, Vec<3> & grad) const + { + if(spline_coefficient.Size() == 0) + spline->GetCoeff(spline_coefficient); + + 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("<<point<<") = " << grad << endl; + } + else + { + grad(0) = dFdxbar*v_axis(0); + grad(1) = dFdxbar*v_axis(1); + grad(2) = dFdxbar*v_axis(2); + //(*testout) << "grad2("<<point<<") = " << grad << endl; + } + } + + + void RevolutionFace :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const + { + if(spline_coefficient.Size() == 0) + spline->GetCoeff(spline_coefficient); + + Vec<3> point_minus_p0 = point-p0; + + Point<2> p; + CalcProj0(point_minus_p0,p); + + + if(fabs(p(1)) > 1e-10) + { + const double dFdybar = 2.*spline_coefficient(1)*p(1) + spline_coefficient(2)*p(0) + spline_coefficient(4); + + const double aux = -pow(p(1),-3); + const double aux0 = point_minus_p0(0) - v_axis(0)*p(0); + const double aux1 = point_minus_p0(1) - v_axis(1)*p(0); + const double aux2 = point_minus_p0(2) - v_axis(2)*p(0); + + + const double dybardx = aux0/p(1); + const double dybardy = aux1/p(1); + const double dybardz = aux2/p(1); + + const double dybardxx = aux*aux0*aux0 + (1.-v_axis(0)*v_axis(0))/p(1); + const double dybardyy = aux*aux1*aux1 + (1.-v_axis(1)*v_axis(1))/p(1); + const double dybardzz = aux*aux2*aux2 + (1.-v_axis(2)*v_axis(2))/p(1); + const double dybardxy = aux*aux0*aux1 - v_axis(0)*v_axis(1)/p(1); + const double dybardxz = aux*aux0*aux2 - v_axis(0)*v_axis(2)/p(1); + const double dybardyz = aux*aux1*aux2 - v_axis(1)*v_axis(2)/p(1); + + hesse(0,0) = 2.*spline_coefficient(0)*v_axis(0)*v_axis(0) + 2.*spline_coefficient(2)*v_axis(0)*dybardx + 2.*spline_coefficient(1)*dybardx*dybardx + + dFdybar*dybardxx; + hesse(1,1) = 2.*spline_coefficient(0)*v_axis(1)*v_axis(1) + 2.*spline_coefficient(2)*v_axis(1)*dybardy + 2.*spline_coefficient(1)*dybardy*dybardy + + dFdybar*dybardyy; + hesse(2,2) = 2.*spline_coefficient(0)*v_axis(2)*v_axis(2) + 2.*spline_coefficient(2)*v_axis(2)*dybardz + 2.*spline_coefficient(1)*dybardz*dybardz + + dFdybar*dybardzz; + + hesse(0,1) = hesse(1,0) = 2.*spline_coefficient(0)*v_axis(0)*v_axis(1) + spline_coefficient(2)*v_axis(0)*dybardy + spline_coefficient(2)*dybardx*v_axis(1) + + 2.*spline_coefficient(2)*dybardx*dybardy + dFdybar*dybardxy; + hesse(0,2) = hesse(2,0) = 2.*spline_coefficient(0)*v_axis(0)*v_axis(2) + spline_coefficient(2)*v_axis(0)*dybardz + spline_coefficient(2)*dybardx*v_axis(2) + + 2.*spline_coefficient(2)*dybardx*dybardz + dFdybar*dybardxz; + hesse(1,2) = hesse(2,1) = 2.*spline_coefficient(0)*v_axis(1)*v_axis(2) + spline_coefficient(2)*v_axis(1)*dybardz + spline_coefficient(2)*dybardy*v_axis(2) + + 2.*spline_coefficient(2)*dybardy*dybardz + dFdybar*dybardyz; + + //(*testout) << "hesse1: " << hesse <<endl; + } + else if (fabs(spline_coefficient(2)) + fabs(spline_coefficient(4)) < 1.e-9 && + fabs(spline_coefficient(0)) > 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 <<endl; + + } + else if (fabs(spline_coefficient(1)) + fabs(spline_coefficient(3)) + fabs(spline_coefficient(4)) + fabs(spline_coefficient(5)) < 1.e-9) // line + { + hesse = 0; + //(*testout) << "hesse3: " << hesse <<endl; + } + else + { + (*testout) << "hesse4: " << hesse <<endl; + } + } + + + + double RevolutionFace ::HesseNorm () const + { + if (fabs(spline_coefficient(1)) + fabs(spline_coefficient(3)) + fabs(spline_coefficient(4)) + fabs(spline_coefficient(5)) < 1.e-9) // line + return 0; + + if (fabs(spline_coefficient(2)) + fabs(spline_coefficient(4)) < 1.e-9 && + fabs(spline_coefficient(0)) > 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<const SplineSeg3<2> *>(spline); + const LineSeg<2> * ls = dynamic_cast<const LineSeg<2> *>(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<checkpoints.Size(); i+=2) + { + Vec<2> 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<double> testt; + + if(!isfirst) + testt.Append(0); + if(!islast) + testt.Append(1); + + const SplineSegment3 * s3 = dynamic_cast<const SplineSegment3 *>(&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<testt.Size(); i++) + { + double thisy = fabs(spline.GetPoint(testt[i])(1)); + if(thisy < miny) + miny = thisy; + } + + return max2(splinecurvature,1./miny); + */ + } + + void RevolutionFace :: Project (Point<3> & 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<n; i++) + for(int j=0; j<n; j++) + { + int pi = (n+1)*i+j; + + tas.AddTriangle( TATriangle (id, pi,pi+1,pi+n+1)); + tas.AddTriangle( TATriangle (id, pi+1,pi+n+1,pi+n+2)); + } + } + + + bool RevolutionFace :: BoxIntersectsFace(const Box<3> & 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<const LineSegment*>(&spline); + const SplineSegment3 * spline3 = dynamic_cast<const SplineSegment3*>(&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<checklines_start.Size(); i++) + { + Vec<2> 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 RevolutionFace :: PointInFace (const Point<3> & p, const double eps) const + { + Point<2> p2d; + CalcProj(p,p2d); + + 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); + + if(val > eps) + return IS_OUTSIDE; + if(val < -eps) + return IS_INSIDE; + + return DOES_INTERSECT; + } + + + + void RevolutionFace :: GetRawData(Array<double> & 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), splinecurve(spline_in), + nsplines(spline_in.GetNSplines()) + { + surfaceactive.SetSize(0); + surfaceids.SetSize(0); + + v_axis = p1-p0; + + v_axis.Normalize(); + + if(splinecurve.GetSpline(0).StartPI()(1) <= 0. && + splinecurve.GetSpline(nsplines-1).EndPI()(1) <= 0.) + type = 2; + else if (Dist(splinecurve.GetSpline(0).StartPI(), + splinecurve.GetSpline(nsplines-1).EndPI()) < 1e-7) + type = 1; + else + cerr << "Surface of revolution cannot be constructed" << endl; + + for(int i=0; i<splinecurve.GetNSplines(); i++) + { + RevolutionFace * face = new RevolutionFace(splinecurve.GetSpline(i), + p0,v_axis, + type==2 && i==0, + type==2 && i==splinecurve.GetNSplines()-1); + faces.Append(face); + surfaceactive.Append(1); + surfaceids.Append(0); + } + } + + Revolution::~Revolution() + { + for(int i=0; i<faces.Size(); i++) + delete faces[i]; + } + + + INSOLID_TYPE Revolution :: BoxInSolid (const BoxSphere<3> & box) const + { + for(int i=0; i<faces.Size(); i++) + if(faces[i]->BoxIntersectsFace(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) && i<faces.Size(); i++) + { + bool thisintersects; + bool thisuncertain; + thisintersects = faces[i]->BoxIntersectsFace(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; i<faces.Size(); i++) + { + faces[i]->GetSpline().LineIntersections(a,b,c,points,eps); + + for(int j=0; j<points.Size(); j++) + { + double t = (points[j](0)-p2d(0))/randomx; + + //(*testout) << t << endl; + if ( t < -eps ) + intersections_before++; + else if ( t > eps ) + intersections_after++; + else + { + intersecting_face = i; + return DOES_INTERSECT; + } + } + } + + if(intersections_before % 2 == 0) + return IS_OUTSIDE; + else + return IS_INSIDE; + } + + 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<int> intersecting_faces; + + for(int i=0; i<faces.Size(); i++) + if(faces[i]->PointInFace(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<const SplineSeg3<2> *>(&faces[intersecting_faces[0]]->GetSpline()); + const LineSeg<2> * linesegment = + dynamic_cast<const LineSeg<2> *>(&faces[intersecting_faces[0]]->GetSpline()); + + Vec<2> t1,t2; + + if(linesegment) + t1 = linesegment->StartPI() - linesegment->EndPI(); + else if(splinesegment3) + t1 = splinesegment3->TangentPoint() - splinesegment3->EndPI(); + + linesegment = + dynamic_cast<const LineSeg<2> *>(&faces[intersecting_faces[1]]->GetSpline()); + splinesegment3 = + dynamic_cast<const SplineSeg3<2> *>(&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; i<faces.Size(); i++) + surfaceactive[i] = (faces[i]->BoxIntersectsFace(box)); + //surfaceactive[i] = (faces[i]->BoxIntersectsFace(box,dummy)); + } + + void Revolution :: UnReduce () + { + for(int i=0; i<faces.Size(); i++) + surfaceactive[i] = true; + } +} diff --git a/contrib/Netgen/libsrc/csg/revolution.hpp b/contrib/Netgen/libsrc/csg/revolution.hpp new file mode 100644 index 0000000000..f1c719febb --- /dev/null +++ b/contrib/Netgen/libsrc/csg/revolution.hpp @@ -0,0 +1,153 @@ +#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; + + mutable Vector spline_coefficient; + + + 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<double> & raw_data); + + ~RevolutionFace(); + + 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 PointInFace (const Point<3> & p, const double eps) const; + + void GetRawData(Array<double> & data) const; + + }; + + + + /* + + Primitive of revolution + + */ + + + class Revolution : public Primitive + { + private: + Point<3> p0,p1; + Vec<3> v_axis; + const SplineGeometry<2> & splinecurve; + const int nsplines; + + // 1 ... torus-like + // 2 ... sphere-like + int type; + + + Array<RevolutionFace*> faces; + + mutable int intersecting_face; + + public: + Revolution(const Point<3> & p0_in, + const Point<3> & p1_in, + const SplineGeometry<2> & spline_in); + + ~Revolution(); + + + /* + 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 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 diff --git a/contrib/Netgen/libsrc/csg/singularref.cpp b/contrib/Netgen/libsrc/csg/singularref.cpp new file mode 100644 index 0000000000..0ad13db9cf --- /dev/null +++ b/contrib/Netgen/libsrc/csg/singularref.cpp @@ -0,0 +1,217 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +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<int> 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<int> 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); +} +} diff --git a/contrib/Netgen/libsrc/csg/singularref.hpp b/contrib/Netgen/libsrc/csg/singularref.hpp new file mode 100644 index 0000000000..c029fbef59 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/singularref.hpp @@ -0,0 +1,84 @@ +#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 SingularFace + { + public: + int domnr; + const Solid *sol; + double factor; + // Array<Point<3> > points; + // Array<INDEX_2> 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 SingularEdge + { + public: + double beta; + int domnr; + const CSGeometry& geom; + const Solid *sol1, *sol2; + Array<Point<3> > points; + Array<INDEX_2> 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 SingularPoint + { + public: + double beta; + const Solid *sol1, *sol2, *sol3; + Array<Point<3> > 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 diff --git a/contrib/Netgen/libsrc/csg/solid.cpp b/contrib/Netgen/libsrc/csg/solid.cpp new file mode 100644 index 0000000000..aba39d8a57 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/solid.cpp @@ -0,0 +1,1732 @@ +#include <mystdlib.h> + +#include <linalg.hpp> +#include <csg.hpp> + + +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; + } + + Solid :: Solid (optyp aop, Solid * as1, Solid * as2) + { + op = aop; + s1 = as1; + s2 = as2; + prim = NULL; + name = NULL; + maxh = 1e10; + } + + 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<Solid*> & solids); + static Solid * CreateSolidTerm (istream & ist, const SYMBOLTABLE<Solid*> & solids); + static Solid * CreateSolidPrim (istream & ist, const SYMBOLTABLE<Solid*> & 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<Solid*> & 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<Solid*> & 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<Solid*> & 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.Get(str); + if (s1) + { + // cout << "primitive: " << str << endl; + return s1; + } + cerr << "syntax error" << endl; + + return NULL; + } + + + Solid * Solid :: CreateSolid (istream & ist, const SYMBOLTABLE<Solid*> & 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<int> & bounds) const + { + int in, strin; + bounds.SetSize (0); + RecBoundaries (p, bounds, in, strin); + } + + void Solid :: RecBoundaries (const Point<3> & p, Array<int> & 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<int> 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<int> 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<int> & 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<int> & 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<int> & 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<int> & 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<int> & 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<int> & 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<int> & 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<int> & 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 + { + 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<int> & surfind) const + { + surfind.SetSize (0); + RecGetSurfaceIndices (surfind); + } + + void Solid :: RecGetSurfaceIndices (Array<int> & 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 :: GetTangentialSurfaceIndices (const Point<3> & p, Array<int> & surfind, double eps) const + { + surfind.SetSize (0); + RecGetTangentialSurfaceIndices (p, surfind, eps); + } + + void Solid :: RecGetTangentialSurfaceIndices (const Point<3> & p, Array<int> & 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<int> & surfind, double eps) const + { + surfind.SetSize (0); + RecGetTangentialSurfaceIndices2 (p, v, surfind, eps); + } + + void Solid :: RecGetTangentialSurfaceIndices2 (const Point<3> & p, const Vec<3> & v, + Array<int> & 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<int> & 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<int> & 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<int> & 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<Point<3> > & 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<Point<3> > & 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)); +} diff --git a/contrib/Netgen/libsrc/csg/solid.hpp b/contrib/Netgen/libsrc/csg/solid.hpp new file mode 100644 index 0000000000..ebd7c88c98 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/solid.hpp @@ -0,0 +1,246 @@ +#ifndef FILE_SOLID +#define FILE_SOLID + +/**************************************************************************/ +/* File: solid.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 1. Dez. 95 */ +/**************************************************************************/ + +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; + + // static int cntnames; + + public: + Solid (Primitive * aprim); + Solid (optyp aop, Solid * as1, Solid * as2 = NULL); + ~Solid (); + + 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<int> & bounds) const; + int NumPrimitives () const; + void GetSurfaceIndices (Array<int> & surfind) const; + void GetSurfaceIndices (IndexSet & iset) const; + + void GetTangentialSurfaceIndices (const Point<3> & p, Array<int> & surfids, double eps) const; + void GetTangentialSurfaceIndices2 (const Point<3> & p, const Vec<3> & v, Array<int> & surfids, double eps) const; + void GetTangentialSurfaceIndices3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, Array<int> & surfids, double eps) 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<int> & 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<int> & 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<int> & 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<int> & surfids, double eps) const; + + + void CalcOnePrimitiveSpecialPoints (const Box<3> & box, Array<Point<3> > & 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<Solid*> & 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<int> & bounds, + int & in, int & strin) const; + /// + void RecTangentialSolid (const Point<3> & p, Solid *& tansol, Array<int> & surfids, + int & in, int & strin, double eps) const; + + void RecTangentialSolid2 (const Point<3> & p, const Vec<3> & vec, + Solid *& tansol, Array<int> & 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<int> & 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<int> & 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<int> & surfind) const; + void RecGetTangentialSurfaceIndices (const Point<3> & p, Array<int> & surfids, double eps) const; + void RecGetTangentialSurfaceIndices2 (const Point<3> & p, const Vec<3> & v, Array<int> & surfids, double eps) const; + void RecGetTangentialSurfaceIndices3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, + Array<int> & surfids, double eps) const; + void RecGetTangentialEdgeSurfaceIndices (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, const Vec<3> & m, + Array<int> & surfids, double eps) const; + void RecGetSurfaceIndices (IndexSet & iset) const; + + void RecCalcOnePrimitiveSpecialPoints (Array<Point<3> > & 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 + { + const 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 diff --git a/contrib/Netgen/libsrc/csg/specpoin.cpp b/contrib/Netgen/libsrc/csg/specpoin.cpp new file mode 100644 index 0000000000..f4c5f946a9 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/specpoin.cpp @@ -0,0 +1,2099 @@ +#include <mystdlib.h> +#include <meshing.hpp> +#include <csg.hpp> + + +/* + 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<Box<3> > 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<int> numprim_hist; + + SpecialPointCalculation :: SpecialPointCalculation () + { + ideps = 1e-9; + } + + void SpecialPointCalculation :: + CalcSpecialPoints (const CSGeometry & ageometry, + Array<MeshPoint> & 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<Point<3> > 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<CloseSurfaceIdentification * >(geometry->identifications[i]); + + if(!ident || !ident->IsSkewIdentification()) + continue; + + for(int j=0; j<points->Size(); 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()); + } + + + bool decision; + bool possiblecrossp, possibleexp; // possible cross or extremalpoint + bool surecrossp = 0, sureexp = 0; // sure ... + + static Array<int> locsurf; // attention: array is static + + 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<const QuadraticSurface*> + (geometry->GetSurface(locsurf[i])); + + if (qsurfi) nquad++; + if (dynamic_cast<const Plane*> (qsurfi)) + nplane++; + else + { + quadi = i; + qsurf = qsurfi; + } + + if (dynamic_cast<const Sphere*> (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<Point<3> > pts; + Array<int> 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<const Plane*> (geometry->GetSurface(locsurf[k1])), + dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k2])), + dynamic_cast<const Plane*> (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; jj<surfids.Size(); jj++) + { + int actrep = geometry->GetSurfaceClassRepresentant(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<const Plane*> (geometry->GetSurface(locsurf[k1])), + dynamic_cast<const Plane*> (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; jj<surfids.Size(); jj++) + { + int actrep = geometry->GetSurfaceClassRepresentant(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<const Plane*> (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<Point<3> > pts; + Array<int> 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<const Sphere*> (geometry->GetSurface(locsurf[k1])), + dynamic_cast<const Sphere*> (geometry->GetSurface(locsurf[k2])), + dynamic_cast<const Sphere*> (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; jj<surfids.Size(); jj++) + { + int actrep = geometry->GetSurfaceClassRepresentant(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<const Sphere*> (geometry->GetSurface(locsurf[k1])), + dynamic_cast<const Sphere*> (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<int> 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 << 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 decideable: 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<Point<3> > & 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<Point<3> > & 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<Point<3> > & 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<Point<3> > & 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<Point<3> > & 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)) > v12(dir)) + dir = j; + + // *testout << "dir = " << dir << endl; + + 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<MeshPoint> & apoints, + Array<SpecialPoint> & specpoints) + { + static int timer = NgProfiler::CreateTimer ("CSG: analyze special points"); + NgProfiler::RegionTimer reg (timer); + + + Array<int> surfind, rep_surfind, surfind2, rep_surfind2, surfind3; + + Array<Vec<3> > normalvecs; + Vec<3> nsurf = 0.0; + + Array<int> 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<double> 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<int> 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<const Polyhedra*> (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<int> 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) + { + spi = specpoints.Append (SpecialPoint()) - 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<specpoints.Size(); i++) + { + if(testuncond.Test(i)) + continue; + + Array<int> same; + same.Append(i); + + for(int j = i+1; j<specpoints.Size(); j++) + { + if(Dist(specpoints[i].p,specpoints[j].p) < 1e-20) + { + same.Append(j); + testuncond.Set(j); + } + } + + if(same.Size() < 3) + for(int j=0; j<same.Size(); j++) + { + (*testout) << "setting " << specpoints[same[j]].p << "; " << specpoints[same[j]].v << "; " + <<specpoints[same[j]].unconditional << " to conditional" << endl; + specpoints[same[j]].unconditional=0; + } + } + */ + + + // if special point is unconditional on some solid, + // it must be unconditional everywhere: + + BitArray uncond (apoints.Size()); + uncond.Clear(); + + for (int i = 0; i < specpoints.Size(); i++) + if (specpoints[i].unconditional) + uncond.Set (specpoint2point[i]); + + for (int i = 0; i < specpoints.Size(); i++) + specpoints[i].unconditional = + uncond.Test (specpoint2point[i]) ? 1 : 0; + } +} diff --git a/contrib/Netgen/libsrc/csg/specpoin.hpp b/contrib/Netgen/libsrc/csg/specpoin.hpp new file mode 100644 index 0000000000..a6d850c932 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/specpoin.hpp @@ -0,0 +1,191 @@ +#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<MeshPoint> * points; + /// + Array<long int> 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<MeshPoint> & points); + /// + void AnalyzeSpecialPoints (const CSGeometry & geometry, + Array<MeshPoint> & points, + Array<SpecialPoint> & 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<Point<3> > & pts); + + void ComputeExtremalPoints (const Sphere * sphere1, + const Sphere * sphere2, + Array<Point<3> > & pts); + + + void ComputeCrossPoints (const Plane * plane1, + const Plane * plane2, + const Plane * plane3, + Array<Point<3> > & pts); + + void ComputeCrossPoints (const Plane * plane1, + const Plane * plane2, + const QuadraticSurface * quadratic, + Array<Point<3> > & pts); + + void ComputeCrossPoints (const Sphere * sphere1, + const Sphere * sphere2, + const Sphere * sphere3, + Array<Point<3> > & pts); + }; + +} + +#endif + + diff --git a/contrib/Netgen/libsrc/csg/spline3d.cpp b/contrib/Netgen/libsrc/csg/spline3d.cpp new file mode 100644 index 0000000000..b89e7f7093 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/spline3d.cpp @@ -0,0 +1,355 @@ +#include <mystdlib.h> + +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> + + +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; +} +} diff --git a/contrib/Netgen/libsrc/csg/spline3d.hpp b/contrib/Netgen/libsrc/csg/spline3d.hpp new file mode 100644 index 0000000000..db3a40c56d --- /dev/null +++ b/contrib/Netgen/libsrc/csg/spline3d.hpp @@ -0,0 +1,99 @@ +namespace 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<splinesegment3d *> 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; + }; + + +} + diff --git a/contrib/Netgen/libsrc/csg/surface.cpp b/contrib/Netgen/libsrc/csg/surface.cpp new file mode 100644 index 0000000000..fe0415ec72 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/surface.cpp @@ -0,0 +1,568 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <csg.hpp> + +#include <linalg.hpp> +#include <meshing.hpp> + + +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, 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<double> & coeffs) const +{ + classname = "undef"; + coeffs.SetSize (0); +} + +void Primitive :: SetPrimitiveData (Array<double> & 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<int> & 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<int> & 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<int> & 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; + } +} +} diff --git a/contrib/Netgen/libsrc/csg/surface.hpp b/contrib/Netgen/libsrc/csg/surface.hpp new file mode 100644 index 0000000000..21821241ee --- /dev/null +++ b/contrib/Netgen/libsrc/csg/surface.hpp @@ -0,0 +1,374 @@ +#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: + + 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, 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 + { + + public: + + Primitive (); + + virtual ~Primitive(); + + + /* + 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<int> & 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<int> & surfind, double eps) const; + + virtual void GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, + Array<int> & surfind, double eps) const; + + + virtual void CalcSpecialPoints (Array<Point<3> > & /* pts */) const { ; } + virtual void AnalyzeSpecialPoint (const Point<3> & /* pt */, + Array<Point<3> > & /* 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; + + Array<int> surfaceids; + Array<int> surfaceactive; + + 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<double> & coeffs) const; + virtual void SetPrimitiveData (Array<double> & 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 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 descibed 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 diff --git a/contrib/Netgen/libsrc/csg/triapprox.cpp b/contrib/Netgen/libsrc/csg/triapprox.cpp new file mode 100644 index 0000000000..0c4f2b14de --- /dev/null +++ b/contrib/Netgen/libsrc/csg/triapprox.cpp @@ -0,0 +1,59 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> + + +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<int> 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); + } +} diff --git a/contrib/Netgen/libsrc/csg/triapprox.hpp b/contrib/Netgen/libsrc/csg/triapprox.hpp new file mode 100644 index 0000000000..c17a3e9466 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/triapprox.hpp @@ -0,0 +1,63 @@ +#ifndef FILE_TRIAPPROX +#define FILE_TRIAPPROX + +/**************************************************************************/ +/* File: triapprox.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 2. Mar. 98 */ +/**************************************************************************/ + + +namespace netgen +{ + + /** + Triangulated approxiamtion 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<Point<3> > points; + Array<Vec<3> > normals; + Array<TATriangle> 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 diff --git a/contrib/Netgen/libsrc/csg/vscsg.cpp b/contrib/Netgen/libsrc/csg/vscsg.cpp new file mode 100644 index 0000000000..a49f3a0db8 --- /dev/null +++ b/contrib/Netgen/libsrc/csg/vscsg.cpp @@ -0,0 +1,559 @@ +#include <mystdlib.h> +#include "incvis.hpp" + +#include <myadt.hpp> +#include <meshing.hpp> +#include <csg.hpp> +#include <stlgeom.hpp> + +#include <visual.hpp> + +#include "vscsg.hpp" + +namespace netgen +{ + + + + /* *********************** Draw Geometry **************** */ + + extern AutoPtr<Mesh> mesh; + extern Array<SpecialPoint> specpoints; + extern Array<Box<3> > boxes; + + + extern Array<Point<3> > project1, project2; + + + // extern AutoPtr<CSGeometry> geometry; + + + VisualSceneGeometry :: VisualSceneGeometry () + : VisualScene() + { + selsurf = 0; + } + + VisualSceneGeometry :: ~VisualSceneGeometry () + { + ; + } + + void VisualSceneGeometry :: SelectSurface (int aselsurf) + { + selsurf = aselsurf; + DrawScene(); + } + + + void VisualSceneGeometry :: DrawScene () + { + int i; + + 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(); + 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); + + glEnable (GL_NORMALIZE); + + for (i = 0; i < geometry->GetNTopLevelObjects(); i++) + { + const TopLevelObject * tlo = geometry -> GetTopLevelObject (i); + if (tlo->GetVisible() && !tlo->GetTransparent()) + { + float mat_col[] = { tlo->GetRed(), tlo->GetGreen(), 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 (i = 0; i < geometry->GetNTopLevelObjects(); i++) + { + const TopLevelObject * tlo = geometry -> GetTopLevelObject (i); + if (tlo->GetVisible() && tlo->GetTransparent()) + { + float mat_col[] = { tlo->GetRed(), tlo->GetGreen(), tlo->GetBlue(), transp }; + + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); + + glCallList (trilists[i]); + } + } + + glDisable (GL_POLYGON_OFFSET_FILL); + + /* + cout << "draw " << project1.Size() << " lines " << endl; + glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); + glLineWidth (1.0f); + glEnable (GL_COLOR_MATERIAL); + + glColor3f (1.0f, 0.0f, 0.0f); + + glBegin (GL_LINES); + for (int i = 0; i < project1.Size(); i++) + { + glVertex3dv (project1[i]); + glVertex3dv (project2[i]); + } + glEnd(); + */ + + + glPopMatrix(); + glDisable(GL_CLIP_PLANE0); + + + + /* + glFlush(); + + int err; + do + { + err = glGetError(); + // cout << "glerr,1 = " << err << endl; + } + while (err != GL_NO_ERROR); + + + // CreateTexture (0, 1, GL_DECAL); + CreateTexture (0, 1, GL_MODULATE); + glEnable (GL_TEXTURE_1D); + + float mat_col[] = { 1.0, 1.0, 1.0 }; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); + + glDisable (GL_BLEND); + glDisable (GL_COLOR_MATERIAL); + glEnable (GL_NORMALIZE); + + if (geometry->GetNTopLevelObjects()) + { + cout << "call list" << endl; + glCallList (trilists[0]); + } + + glColor3d (1.0, 1.0, 1.0); + + glBegin (GL_TRIANGLES); + glNormal3f (0, 0, 1); + SetOpenGlColor (-1.0, 0, 1, 0); + glVertex3f (0.0, 0.0, 0.0); + SetOpenGlColor (0.5, 0, 1, 0); + glNormal3f (0, 0, 1); + glVertex3f (1.0, 0.0, 0.0); + SetOpenGlColor (2.0, 0, 1, 0); + glNormal3f (0, 0, 1); + glVertex3f (0.0, 1.0, 0.0); + + glEnd (); + + cout << "trig drawn" << endl; + + glDisable (GL_TEXTURE_1D); + glDisable (GL_COLOR_MATERIAL); + glFlush(); + + cout << "glerr,2 = " << glGetError() << endl; + */ + + + + DrawCoordinateCross (); + DrawNetgenLogo (); + + glFinish(); + } + + + void VisualSceneGeometry :: BuildScene (int zoomall) + { + 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) + { + glBegin (GL_TRIANGLES); + for (int j = 0; j < ta.GetNT(); j++) + { + for (int k = 0; k < 3; k++) + { + int pi = ta.GetTriangle(j)[k]; + glNormal3dv (ta.GetNormal (pi)); + glVertex3dv (ta.GetPoint(pi)); + } + } + 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(); + glMultMatrixf (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] = { 1 - backcolor, + 1 - backcolor, + 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]); + } + } + + if (vispar.drawedpointnrs) + { + glEnable (GL_COLOR_MATERIAL); + GLfloat textcol[3] = { 1 - backcolor, + 1 - backcolor, + 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++) + { + const Point3d & p = mesh->Point(i); + glRasterPos3d (p.X(), p.Y(), p.Z()); + + sprintf (buf, "%d", 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(); + } + + + + + + +} + + diff --git a/contrib/Netgen/libsrc/csg/vscsg.hpp b/contrib/Netgen/libsrc/csg/vscsg.hpp new file mode 100644 index 0000000000..c32f5da83a --- /dev/null +++ b/contrib/Netgen/libsrc/csg/vscsg.hpp @@ -0,0 +1,34 @@ +#ifndef FILE_VSCSG +#define FILE_VSCSG + +/**************************************************************************/ +/* File: vscsg.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 05. Jan. 2011 */ +/**************************************************************************/ + +namespace netgen +{ + + class VisualSceneGeometry : public VisualScene + { + class CSGeometry * geometry; + Array<int> 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 diff --git a/contrib/Netgen/libsrc/general/Makefile.am b/contrib/Netgen/libsrc/general/Makefile.am new file mode 100644 index 0000000000..9c555b0238 --- /dev/null +++ b/contrib/Netgen/libsrc/general/Makefile.am @@ -0,0 +1,14 @@ +noinst_HEADERS = array.hpp myadt.hpp optmem.hpp sort.hpp table.hpp autodiff.hpp flags.hpp mystring.hpp spbita2d.hpp template.hpp autoptr.hpp hashtabl.hpp netgenout.hpp profiler.hpp stack.hpp bitarray.hpp seti.hpp symbolta.hpp dynamicmem.hpp parthreads.hpp mpi_interface.hpp + +# moveablemem.hpp + +include_HEADERS = ngexception.hpp + +AM_CPPFLAGS = $(MPI_INCLUDES) -I$(top_srcdir)/libsrc/include +METASOURCES = AUTO +noinst_LTLIBRARIES = libgen.la +libgen_la_SOURCES = array.cpp bitarray.cpp dynamicmem.cpp flags.cpp \ + hashtabl.cpp mystring.cpp ngexception.cpp optmem.cpp parthreads.cpp \ + profiler.cpp seti.cpp sort.cpp spbita2d.cpp symbolta.cpp table.cpp + +# moveablemem.cpp diff --git a/contrib/Netgen/libsrc/general/array.cpp b/contrib/Netgen/libsrc/general/array.cpp new file mode 100644 index 0000000000..d3f48d36cc --- /dev/null +++ b/contrib/Netgen/libsrc/general/array.cpp @@ -0,0 +1,75 @@ +#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 <mystdlib.h> +#include <myadt.hpp> +#include <assert.h> + + +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<char*> (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 + diff --git a/contrib/Netgen/libsrc/general/array.hpp b/contrib/Netgen/libsrc/general/array.hpp new file mode 100644 index 0000000000..40b6048d38 --- /dev/null +++ b/contrib/Netgen/libsrc/general/array.hpp @@ -0,0 +1,661 @@ +#ifndef FILE_Array +#define FILE_Array + +/**************************************************************************/ +/* File: array.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + + +namespace netgen +{ + + // template <class T, int B1, int B2> class IndirectArray; + + + + /** + 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 T, int BASE = 0> + class FlatArray + { + protected: + /// the size + int size; + /// the data + T * data; + public: + + /// provide size and memory + FlatArray (int asize, T * adata) + : size(asize), data(adata) { ; } + + /// the size + int Size() const { return size; } + + int Begin() const { return BASE; } + int End() const { return size+BASE; } + + /// Access array. BASE-based + T & operator[] (int 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]; + } + + /// 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<T> Range (int start, int end) + { + return FlatArray<T> (end-start, data+start); + } + + /// first position of element elem, returns -1 if element not contained in array + int Pos(const T & elem) const + { + int pos = -1; + for(int 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 <class T, int BASE> + inline ostream & operator<< (ostream & s, const FlatArray<T,BASE> & a) + { + for (int i = a.Begin(); i < a.End(); i++) + s << i << ": " << a[i] << endl; + return s; + } + + + + /** + Dynamic array container. + + Array<T> 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 T, int BASE = 0> + class Array : public FlatArray<T, BASE> + { + protected: + using FlatArray<T,BASE>::size; + using FlatArray<T,BASE>::data; + + /// physical size of array + int allocsize; + /// memory is responsibility of container + bool ownmem; + + public: + + /// Generate array of logical and physical size asize + explicit Array(int asize = 0) + : FlatArray<T, BASE> (asize, asize ? new T[asize] : 0) + { + allocsize = asize; + ownmem = 1; + } + + /// Generate array in user data + Array(int asize, T* adata) + : FlatArray<T, BASE> (asize, adata) + { + allocsize = asize; + ownmem = 0; + } + + /// array copy + explicit Array (const Array<T> & a2) + : FlatArray<T, BASE> (a2.Size(), a2.Size() ? new T[a2.Size()] : 0) + { + allocsize = size; + ownmem = 1; + for (int i = BASE; i < size+BASE; i++) + (*this)[i] = a2[i]; + } + + + + /// if responsible, deletes memory + ~Array() + { + if (ownmem) + delete [] data; + } + + /// Change logical size. If necessary, do reallocation. Keeps contents. + void SetSize(int nsize) + { + if (nsize > allocsize) + ReSize (nsize); + size = nsize; + } + + /// Change physical size. Keeps logical size. Keeps contents. + void SetAllocSize (int nallocsize) + { + if (nallocsize > allocsize) + ReSize (nallocsize); + } + + + /// Add element at end of array. reallocation if necessary. + int Append (const T & el) + { + if (size == allocsize) + ReSize (size+1); + data[size] = el; + size++; + return size; + } + + template <typename T2, int B2> + void Append (FlatArray<T2, B2> 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 (int i) + { +#ifdef CHECK_Array_RANGE + RangeCheck (i+1); +#endif + + data[i] = data[size-1]; + size--; + // DeleteElement (i+1); + } + + + /// Delete element i (1-based). Move last element to position i. + void DeleteElement (int i) + { +#ifdef CHECK_Array_RANGE + RangeCheck (i); +#endif + + data[i-1] = 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<T, BASE>::operator= (val); + return *this; + } + + /// array copy + Array & operator= (const Array & a2) + { + SetSize (a2.Size()); + for (int i = BASE; i < size+BASE; i++) + (*this)[i] = a2[i]; + return *this; + } + + /// array copy + Array & operator= (const FlatArray<T> & a2) + { + SetSize (a2.Size()); + for (int i = BASE; i < size+BASE; i++) + (*this)[i] = a2[i]; + return *this; + } + + + private: + + /// resize array, at least to size minsize. copy contents + void ReSize (int minsize) + { + int nsize = 2 * allocsize; + if (nsize < minsize) nsize = minsize; + + if (data) + { + T * p = new T[nsize]; + + int mins = (nsize < size) ? nsize : size; + memcpy (p, data, mins * sizeof(T)); + + if (ownmem) + delete [] data; + ownmem = 1; + data = p; + } + else + { + data = new T[nsize]; + ownmem = 1; + } + + allocsize = nsize; + } + }; + + + + template <class T, int S> + class ArrayMem : public Array<T> + { + using Array<T>::size; + using Array<T>::data; + using Array<T>::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(int asize = 0) + : Array<T> (S, static_cast<T*> (static_cast<void*>(&mem[0]))) + { + size = asize; + if (asize > S) + { + data = new T[asize]; + ownmem = 1; + } + // SetSize (asize); + } + + ArrayMem & operator= (const T & val) + { + Array<T>::operator= (val); + return *this; + } + + /// array copy + ArrayMem & operator= (const FlatArray<T> & a2) + { + SetSize (a2.Size()); + for (int i = 0; i < size; i++) + (*this)[i] = a2[i]; + return *this; + } + + }; + + + + + + /* + template <class T, int B1, int B2> + class IndirectArray + { + const FlatArray<T, B1> & array; + const FlatArray<int, B2> & ia; + + public: + IndirectArray (const FlatArray<T,B1> & aa, const FlatArray<int, B2> & aia) + : array(aa), ia(aia) { ; } + int Size() const { return ia.Size(); } + const T & operator[] (int i) const { return array[ia[i]]; } + }; + */ + + + + + + + + + + /// + template <class T, int BASE = 0> + class MoveableArray + { + int size; + int allocsize; + DynamicMem<T> 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 <class T> + inline ostream & operator<< (ostream & ost, MoveableArray<T> & a) + { + for (int i = 0; i < a.Size(); i++) + ost << i << ": " << a[i] << endl; + return ost; + } + + + + /// bubble sort array + template <class T> + inline void BubbleSort (const FlatArray<T> & 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 <class T, class S> + inline void BubbleSort (FlatArray<T> & data, FlatArray<S> & 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 <class T, class S> + void QuickSortRec (FlatArray<T> & data, + FlatArray<S> & 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 <class T, class S> + void QuickSort (FlatArray<T> & data, FlatArray<S> & slave) + { + QuickSortRec (data, slave, 0, data.Size()-1); + } + + + + + + + + + + template <class T> + void Intersection (const FlatArray<T> & in1, const FlatArray<T> & in2, + Array<T> & out) + { + out.SetSize(0); + for(int i=0; i<in1.Size(); i++) + if(in2.Contains(in1[i])) + out.Append(in1[i]); + } + template <class T> + void Intersection (const FlatArray<T> & in1, const FlatArray<T> & in2, const FlatArray<T> & in3, + Array<T> & out) + { + out.SetSize(0); + for(int i=0; i<in1.Size(); i++) + if(in2.Contains(in1[i]) && in3.Contains(in1[i])) + out.Append(in1[i]); + } + + +} + +#endif + diff --git a/contrib/Netgen/libsrc/general/autodiff.hpp b/contrib/Netgen/libsrc/general/autodiff.hpp new file mode 100644 index 0000000000..e2ba63d0e7 --- /dev/null +++ b/contrib/Netgen/libsrc/general/autodiff.hpp @@ -0,0 +1,351 @@ +#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 <int D, typename SCAL = double> +class AutoDiff +{ + SCAL val; + SCAL dval[D]; +public: + + typedef AutoDiff<D,SCAL> 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<D,SCAL> & operator+= (const AutoDiff<D,SCAL> & y) throw() + { + val += y.val; + for (int i = 0; i < D; i++) + dval[i] += y.dval[i]; + return *this; + } + + /// + AutoDiff<D,SCAL> & operator-= (const AutoDiff<D,SCAL> & y) throw() + { + val -= y.val; + for (int i = 0; i < D; i++) + dval[i] -= y.dval[i]; + return *this; + + } + + /// + AutoDiff<D,SCAL> & operator*= (const AutoDiff<D,SCAL> & 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<D,SCAL> & operator*= (const SCAL & y) throw() + { + val *= y; + for (int i = 0; i < D; i++) + dval[i] *= y; + return *this; + } + + /// + AutoDiff<D,SCAL> & 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<int D, typename SCAL> +inline ostream & operator<< (ostream & ost, const AutoDiff<D,SCAL> & x) +{ + ost << x.Value() << ", D = "; + for (int i = 0; i < D; i++) + ost << x.DValue(i) << " "; + return ost; +} + +/// AutoDiff plus AutoDiff +template<int D, typename SCAL> +inline AutoDiff<D,SCAL> operator+ (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y) throw() +{ + AutoDiff<D,SCAL> res; + res.Value () = x.Value()+y.Value(); + // AutoDiff<D,SCAL> 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<int D, typename SCAL> +inline AutoDiff<D,SCAL> operator- (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y) throw() +{ + AutoDiff<D,SCAL> res; + res.Value() = x.Value()-y.Value(); + // AutoDiff<D,SCAL> 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<int D, typename SCAL> +inline AutoDiff<D,SCAL> operator+ (double x, const AutoDiff<D,SCAL> & y) throw() +{ + AutoDiff<D,SCAL> 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<int D, typename SCAL> +inline AutoDiff<D,SCAL> operator+ (const AutoDiff<D,SCAL> & y, double x) throw() +{ + AutoDiff<D,SCAL> res; + res.Value() = x+y.Value(); + for (int i = 0; i < D; i++) + res.DValue(i) = y.DValue(i); + return res; +} + + +/// minus AutoDiff +template<int D, typename SCAL> +inline AutoDiff<D,SCAL> operator- (const AutoDiff<D,SCAL> & x) throw() +{ + AutoDiff<D,SCAL> res; + res.Value() = -x.Value(); + for (int i = 0; i < D; i++) + res.DValue(i) = -x.DValue(i); + return res; +} + +/// AutoDiff minus double +template<int D, typename SCAL> +inline AutoDiff<D,SCAL> operator- (const AutoDiff<D,SCAL> & x, double y) throw() +{ + AutoDiff<D,SCAL> res; + res.Value() = x.Value()-y; + for (int i = 0; i < D; i++) + res.DValue(i) = x.DValue(i); + return res; +} + +/// +template<int D, typename SCAL> +inline AutoDiff<D,SCAL> operator- (double x, const AutoDiff<D,SCAL> & y) throw() +{ + AutoDiff<D,SCAL> 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<int D, typename SCAL> +inline AutoDiff<D,SCAL> operator* (double x, const AutoDiff<D,SCAL> & y) throw() +{ + AutoDiff<D,SCAL> 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<int D, typename SCAL> +inline AutoDiff<D,SCAL> operator* (const AutoDiff<D,SCAL> & y, double x) throw() +{ + AutoDiff<D,SCAL> 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<int D, typename SCAL> +inline AutoDiff<D,SCAL> operator* (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y) throw() +{ + AutoDiff<D,SCAL> 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<int D, typename SCAL> +inline AutoDiff<D,SCAL> sqr (const AutoDiff<D,SCAL> & x) throw() +{ + AutoDiff<D,SCAL> 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<int D, typename SCAL> +inline AutoDiff<D,SCAL> Inv (const AutoDiff<D,SCAL> & x) +{ + AutoDiff<D,SCAL> 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<int D, typename SCAL> +inline AutoDiff<D,SCAL> operator/ (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y) +{ + return x * Inv (y); +} + +/// AutoDiff div double +template<int D, typename SCAL> +inline AutoDiff<D,SCAL> operator/ (const AutoDiff<D,SCAL> & x, double y) +{ + return (1/y) * x; +} + +/// double div AutoDiff +template<int D, typename SCAL> +inline AutoDiff<D,SCAL> operator/ (double x, const AutoDiff<D,SCAL> & y) +{ + return x * Inv(y); +} + + + + +template<int D, typename SCAL> +inline AutoDiff<D,SCAL> fabs (const AutoDiff<D,SCAL> & x) +{ + double abs = fabs (x.Value()); + AutoDiff<D,SCAL> 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 diff --git a/contrib/Netgen/libsrc/general/autoptr.hpp b/contrib/Netgen/libsrc/general/autoptr.hpp new file mode 100644 index 0000000000..352a6105f8 --- /dev/null +++ b/contrib/Netgen/libsrc/general/autoptr.hpp @@ -0,0 +1,36 @@ +#ifndef FILE_AUTOPTR +#define FILE_AUTOPTR + +/**************************************************************************/ +/* File: autoptr.hpp */ +/* Author: STL, Joachim Schoeberl */ +/* Date: 29. Dec. 02 */ +/**************************************************************************/ + +namespace netgen +{ + +template <typename T> +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 diff --git a/contrib/Netgen/libsrc/general/bitarray.cpp b/contrib/Netgen/libsrc/general/bitarray.cpp new file mode 100644 index 0000000000..1c36e5fc04 --- /dev/null +++ b/contrib/Netgen/libsrc/general/bitarray.cpp @@ -0,0 +1,132 @@ +/**************************************************************************/ +/* File: bitarray.cc */ +/* Autho: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + data type BitArray +*/ + +#include <mystdlib.h> +#include <myadt.hpp> + + +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 <int BASE> + void BitArrayChar<BASE> :: Set () + { + data = 1; + } + + template <int BASE> + void BitArrayChar<BASE> :: Clear () + { + data = 0; + } + + + template <int BASE> + void BitArrayChar<BASE> :: Invert () + { + for (int i = BASE; i < data.Size()+BASE; i++) + data[i] = 1 - data[i]; + } + + template <int BASE> + void BitArrayChar<BASE> :: And (const BitArrayChar & ba2) + { + for (int i = BASE; i < data.Size()+BASE; i++) + data[i] &= ba2.data[i]; + } + + + template <int BASE> + void BitArrayChar<BASE> :: 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>; +} diff --git a/contrib/Netgen/libsrc/general/bitarray.hpp b/contrib/Netgen/libsrc/general/bitarray.hpp new file mode 100644 index 0000000000..64a4ee6e60 --- /dev/null +++ b/contrib/Netgen/libsrc/general/bitarray.hpp @@ -0,0 +1,227 @@ +#ifndef FILE_BitArray +#define FILE_BitArray + +/**************************************************************************/ +/* File: bitarray.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +#include <limits.h> + +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 accoring 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 accoring bit. + No range checking is done. +*/ +template <int BASE = 1> +class BitArrayChar +{ + /// + Array<char,BASE> 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 <int BASE> +inline ostream & operator<< (ostream & s, const BitArrayChar<BASE> & 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 diff --git a/contrib/Netgen/libsrc/general/dynamicmem.cpp b/contrib/Netgen/libsrc/general/dynamicmem.cpp new file mode 100644 index 0000000000..56fb1182ad --- /dev/null +++ b/contrib/Netgen/libsrc/general/dynamicmem.cpp @@ -0,0 +1,201 @@ +#include <myadt.hpp> + +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; + 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<uintptr_t>(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<uintptr_t>(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 + +} diff --git a/contrib/Netgen/libsrc/general/dynamicmem.hpp b/contrib/Netgen/libsrc/general/dynamicmem.hpp new file mode 100644 index 0000000000..a080cbdaa2 --- /dev/null +++ b/contrib/Netgen/libsrc/general/dynamicmem.hpp @@ -0,0 +1,98 @@ +#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; } + const 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 <typename T> +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<const T*> (BaseDynamicMem::Ptr()); + } + + T * Ptr() + { + return reinterpret_cast<T*> (BaseDynamicMem::Ptr()); + } + + operator const T* () const + { + return reinterpret_cast<const T*> (BaseDynamicMem::Ptr()); + } + + operator T* () + { + return reinterpret_cast<T*> (BaseDynamicMem::Ptr()); + } + + void Swap (DynamicMem<T> & m2) + { + BaseDynamicMem::Swap (m2); + } +protected: + DynamicMem (const DynamicMem & m); + DynamicMem & operator= (const DynamicMem & m); +}; + +} + +#endif diff --git a/contrib/Netgen/libsrc/general/flags.cpp b/contrib/Netgen/libsrc/general/flags.cpp new file mode 100644 index 0000000000..e5916f8758 --- /dev/null +++ b/contrib/Netgen/libsrc/general/flags.cpp @@ -0,0 +1,330 @@ +/**************************************************************************/ +/* File: flags.cc */ +/* Author: Joachim Schoeberl */ +/* Date: 10. Oct. 96 */ +/**************************************************************************/ + +/* + Datatype Flags +*/ + +#include <mystdlib.h> +#include <myadt.hpp> + +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<char*> & val) + { + Array<char*> * strarray = new Array<char*>; + 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<double> & val) + { + Array<double> * numarray = new Array<double>; + 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.Get(name); + else + return def; + } + + double Flags :: GetNumFlag (const char * name, double def) const + { + if (numflags.Used (name)) + return numflags.Get(name); + else + return def; + } + + const double * Flags :: GetNumFlagPtr (const char * name) const + { + if (numflags.Used (name)) + return & ((SYMBOLTABLE<double>&)numflags).Elem(name); + else + return NULL; + } + + double * Flags :: GetNumFlagPtr (const char * name) + { + if (numflags.Used (name)) + return & ((SYMBOLTABLE<double>&)numflags).Elem(name); + else + return NULL; + } + + bool Flags :: GetDefineFlag (const char * name) const + { + return defflags.Used (name); + } + + + const Array<char*> & + Flags :: GetStringListFlag (const char * name) const + { + if (strlistflags.Used (name)) + return *strlistflags.Get(name); + else + { + static Array<char*> dummy_array(0); + return dummy_array; + } + } + + const Array<double> & + Flags ::GetNumListFlag (const char * name) const + { + if (numlistflags.Used (name)) + return *numlistflags.Get(name); + else + { + static Array<double> 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.Get(i) << endl; + for (i = 1; i <= numflags.Size(); i++) + outfile << numflags.GetName(i) << " = " << numflags.Get(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.Get(i) << endl; + for (i = 1; i <= numflags.Size(); i++) + ost << numflags.GetName(i) << " = " << numflags.Get(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; + } + } + */ + } +} diff --git a/contrib/Netgen/libsrc/general/flags.hpp b/contrib/Netgen/libsrc/general/flags.hpp new file mode 100644 index 0000000000..810fbfbe6b --- /dev/null +++ b/contrib/Netgen/libsrc/general/flags.hpp @@ -0,0 +1,88 @@ +#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<char *> strflags; + /// + SYMBOLTABLE<double> numflags; + /// + SYMBOLTABLE<int> defflags; + /// + SYMBOLTABLE<Array<char*>*> strlistflags; + /// + SYMBOLTABLE<Array<double>*> 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 falg + DLL_HEADER void SetFlag (const char * name, const Array<char*> & val); + /// Sets double array flag + DLL_HEADER void SetFlag (const char * name, const Array<double> & 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<char*> & GetStringListFlag (const char * name) const; + /// Returns num list flag, empty array if not exist + DLL_HEADER const Array<double> & 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 + diff --git a/contrib/Netgen/libsrc/general/hashtabl.cpp b/contrib/Netgen/libsrc/general/hashtabl.cpp new file mode 100644 index 0000000000..53d7eafb46 --- /dev/null +++ b/contrib/Netgen/libsrc/general/hashtabl.cpp @@ -0,0 +1,326 @@ +/**************************************************************************/ +/* File: hashtabl.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + Abstract data type HASHTABLE +*/ + +#include <algorithm> +#include <mystdlib.h> +#include <myadt.hpp> + +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. acces 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 (int size) + : hash(size) + { + hash.SetName ("i2-hashtable, hash"); + + invalid = -1; + for (int i = 1; i <= size; i++) + hash.Elem(i).I1() = invalid; + } + + void BASE_INDEX_2_CLOSED_HASHTABLE :: + BaseSetSize (int size) + { + hash.SetSize(size); + for (int i = 1; i <= size; i++) + hash.Elem(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; + } + } + + int 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; + if (hash.Get(i) == ind) + { + apos = i; + return 0; + } + if (hash.Get(i).I1() == 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_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) + { + 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"); + } + } +} + diff --git a/contrib/Netgen/libsrc/general/hashtabl.hpp b/contrib/Netgen/libsrc/general/hashtabl.hpp new file mode 100644 index 0000000000..bd82518240 --- /dev/null +++ b/contrib/Netgen/libsrc/general/hashtabl.hpp @@ -0,0 +1,1362 @@ +#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<INDEX,1> 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 T> +class INDEX_HASHTABLE : private BASE_INDEX_HASHTABLE +{ + /// + TABLE<T,1> 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<INDEX_2> hash; + +public: + /// + 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 + { + int i; + for (i = 1; i <= hash.EntrySize (bnr); i++) + if (hash.Get(bnr, i) == ind) + return i; + return 0; + } +}; + + +/// +template <class T> +class INDEX_2_HASHTABLE : public BASE_INDEX_2_HASHTABLE +{ + /// + TABLE<T> cont; + +public: + /// + 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)) ? 1 : 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()]; } +}; + + + +template <typename T> +inline ostream & operator<< (ostream & ost, const INDEX_2_HASHTABLE<T> & ht) +{ + for (typename INDEX_2_HASHTABLE<T>::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<INDEX_3> hash; + +public: + /// + 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 T> +class INDEX_3_HASHTABLE : private BASE_INDEX_3_HASHTABLE +{ + /// + TABLE<T> cont; + +public: + /// + 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()]; } + + + +}; + + + + + + +template <typename T> +inline ostream & operator<< (ostream & ost, const INDEX_3_HASHTABLE<T> & ht) +{ + for (typename INDEX_3_HASHTABLE<T>::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<INDEX> 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 postion 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 T> +class INDEX_CLOSED_HASHTABLE : public BASE_INDEX_CLOSED_HASHTABLE +{ + /// + MoveableArray<T> 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); + } +}; + + + + + + + +/// Closed Hashing HT + +class BASE_INDEX_2_CLOSED_HASHTABLE +{ +protected: + /// + MoveableArray<INDEX_2> hash; + /// + int invalid; +public: + /// + BASE_INDEX_2_CLOSED_HASHTABLE (int size); + + int Size() const { return hash.Size(); } + int UsedPos (int pos) const { return ! (hash.Get(pos).I1() == invalid); } + int UsedElements () const; + + /// + int HashValue (const INDEX_2 & ind) const + { + return (ind.I1() + 71 * ind.I2()) % hash.Size() + 1; + } + + + int Position (const INDEX_2 & ind) const + { + int i = HashValue(ind); + while (1) + { + if (hash.Get(i) == ind) return i; + if (hash.Get(i).I1() == invalid) return 0; + i++; + if (i > hash.Size()) i = 1; + } + } + + // returns 1, if new postion is created + int PositionCreate (const INDEX_2 & ind, int & apos) + { + int i = HashValue (ind); + if (hash.Get(i) == ind) + { + apos = i; + return 0; + } + if (hash.Get(i).I1() == invalid) + { + hash.Elem(i) = ind; + apos = i; + return 1; + } + return PositionCreate2 (ind, apos); + } + +protected: + /// + + int Position2 (const INDEX_2 & ind) const; + int PositionCreate2 (const INDEX_2 & ind, int & apos); + void BaseSetSize (int asize); +}; + + +template <class T> +class INDEX_2_CLOSED_HASHTABLE : public BASE_INDEX_2_CLOSED_HASHTABLE +{ + /// + MoveableArray<T> cont; + +public: + /// + inline INDEX_2_CLOSED_HASHTABLE (int size); + /// + inline void Set (const INDEX_2 & ahash, const T & acont); + /// + inline const T & Get (const INDEX_2 & ahash) const; + /// + inline bool Used (const INDEX_2 & ahash) const; + /// + inline void SetData (int pos, const INDEX_2 & ahash, const T & acont); + /// + inline void GetData (int pos, INDEX_2 & ahash, T & acont) const; + /// + inline void SetData (int pos, const T & acont); + /// + inline void GetData (int pos, T & acont) const; + /// + const T & GetData (int pos) { return cont.Get(pos); } + /// + inline void SetSize (int 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 <typename T> +inline ostream & operator<< (ostream & ost, const INDEX_2_CLOSED_HASHTABLE<T> & ht) +{ + for (int i = 0; i < ht.Size(); i++) + if (ht.UsedPos(i)) + { + INDEX_2 hash; + T data; + ht.GetData (i, hash, data); + ost << "hash = " << hash << ", data = " << data << endl; + } + return ost; +} + + + + + + +class BASE_INDEX_3_CLOSED_HASHTABLE +{ +protected: + MoveableArray<INDEX_3> hash; + int invalid; + +protected: + BASE_INDEX_3_CLOSED_HASHTABLE (int size) + : hash(size) + { + hash.SetName ("i3-hashtable, hash"); + invalid = -1; + for (int 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(); + } + + 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(); + } + } + + 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(); + c++; + } + } + + + + // returns true, if new postion 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); + } + +protected: + bool PositionCreate2 (const INDEX_3 & ind, int & apos); + void BaseSetSize (int asize); +}; + + + +template <class T> +class INDEX_3_CLOSED_HASHTABLE : public BASE_INDEX_3_CLOSED_HASHTABLE +{ + MoveableArray<T,0> cont; + +public: + INDEX_3_CLOSED_HASHTABLE (int size) + : BASE_INDEX_3_CLOSED_HASHTABLE(size), cont(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(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 <typename T> +inline ostream & operator<< (ostream & ost, const INDEX_3_CLOSED_HASHTABLE<T> & 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<class T> +inline INDEX_3_HASHTABLE<T> :: INDEX_3_HASHTABLE (int size) + : BASE_INDEX_3_HASHTABLE (size), cont(size) +{ + ; +} + +template<class T> +inline int INDEX_3_HASHTABLE<T> :: 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<class T> +inline void INDEX_3_HASHTABLE<T> :: 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<class T> +inline const T & INDEX_3_HASHTABLE<T> :: Get (const INDEX_3 & ahash) const +{ + int bnr = HashValue (ahash); + int pos = Position (bnr, ahash); + return cont.Get (bnr, pos); +} + +template<class T> +inline bool INDEX_3_HASHTABLE<T> :: Used (const INDEX_3 & ahash) const +{ + return (Position (HashValue (ahash), ahash)) ? 1 : 0; +} + +template<class T> +inline int INDEX_3_HASHTABLE<T> :: GetNBags () const +{ + return cont.Size(); +} + +template<class T> +inline int INDEX_3_HASHTABLE<T> :: GetBagSize (int bnr) const +{ + return cont.EntrySize (bnr); +} + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: GetData (int bnr, int colnr, INDEX_3 & ahash, T & acont) const +{ + ahash = hash.Get(bnr, colnr); + acont = cont.Get(bnr, colnr); +} + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: SetData (int bnr, int colnr, const INDEX_3 & ahash, const T & acont) +{ + hash.Set(bnr, colnr, ahash); + cont.Set(bnr, colnr, acont); +} + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: SetSize (int size) +{ + hash.SetSize (size); + cont.SetSize (size); +} + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: DeleteData () +{ + int n = hash.Size(); + hash.SetSize (n); + cont.SetSize (n); +} + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: PrepareSet (const INDEX_3 & ahash) +{ + int bnr = HashValue (ahash); + hash.IncSizePrepare (bnr-1); + cont.IncSizePrepare (bnr-1); +} + + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: AllocateElements () +{ + hash.AllocateElementsOneBlock(); + cont.AllocateElementsOneBlock(); +} + + + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: PrintMemInfo (ostream & ost) const + { + ost << "Hash: " << endl; + hash.PrintMemInfo (ost); + ost << "Cont: " << endl; + cont.PrintMemInfo (ost); + } + + + + + +template<class T> +inline INDEX_HASHTABLE<T> :: INDEX_HASHTABLE (int size) + : BASE_INDEX_HASHTABLE (size), cont(size) + { + ; + } + +template<class T> +inline void INDEX_HASHTABLE<T> :: 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<class T> +inline const T & INDEX_HASHTABLE<T> :: Get (const INDEX & ahash) const + { + int bnr = HashValue (ahash); + int pos = Position (bnr, ahash); + return cont.Get (bnr, pos); + } + +template<class T> +inline bool INDEX_HASHTABLE<T> :: Used (const INDEX & ahash) const + { + return (Position (HashValue (ahash), ahash)) ? 1 : 0; + } + +template<class T> +inline int INDEX_HASHTABLE<T> :: GetNBags () const + { + return hash.Size(); + } + +template<class T> +inline int INDEX_HASHTABLE<T> :: GetBagSize (int bnr) const + { + return hash.EntrySize(bnr); + } + +template<class T> +inline void INDEX_HASHTABLE<T> :: GetData (int bnr, int colnr, INDEX & ahash, T & acont) const + { + ahash = hash.Get(bnr, colnr); + acont = cont.Get(bnr, colnr); + } + +template<class T> +inline void INDEX_HASHTABLE<T> :: PrintMemInfo (ostream & ost) const + { + ost << "Hash: " << endl; + hash.PrintMemInfo (ost); + ost << "Cont: " << endl; + cont.PrintMemInfo (ost); + } + + + + + + + + + + + + + + + +/* *********** Closed Hashing ************************* */ + + + +template<class T> +inline INDEX_2_CLOSED_HASHTABLE<T> :: +INDEX_2_CLOSED_HASHTABLE (int size) + : BASE_INDEX_2_CLOSED_HASHTABLE(size), cont(size) +{ + cont.SetName ("i2-hashtable, contents"); +} + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +Set (const INDEX_2 & ahash, const T & acont) +{ + int pos; + PositionCreate (ahash, pos); + hash.Elem(pos) = ahash; + cont.Elem(pos) = acont; +} + +template<class T> +inline const T & INDEX_2_CLOSED_HASHTABLE<T> :: +Get (const INDEX_2 & ahash) const +{ + int pos = Position (ahash); + return cont.Get(pos); +} + +template<class T> +inline bool INDEX_2_CLOSED_HASHTABLE<T> :: +Used (const INDEX_2 & ahash) const +{ + int pos = Position (ahash); + return (pos != 0); +} + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +SetData (int pos, const INDEX_2 & ahash, const T & acont) +{ + hash.Elem(pos) = ahash; + cont.Elem(pos) = acont; +} + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +GetData (int pos, INDEX_2 & ahash, T & acont) const +{ + ahash = hash.Get(pos); + acont = cont.Get(pos); +} + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +SetData (int pos, const T & acont) +{ + cont.Elem(pos) = acont; +} + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +GetData (int pos, T & acont) const +{ + acont = cont.Get(pos); +} + + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +SetSize (int size) +{ + BaseSetSize(size); + cont.SetSize(size); +} + + + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +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<class T> +inline INDEX_3_CLOSED_HASHTABLE<T> :: +INDEX_3_CLOSED_HASHTABLE (int size) + : BASE_INDEX_3_CLOSED_HASHTABLE(size), cont(size) +{ + cont.SetName ("i3-hashtable, contents"); +} + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +Set (const INDEX_3 & ahash, const T & acont) +{ + int pos; + PositionCreate (ahash, pos); + hash.Elem(pos) = ahash; + cont.Elem(pos) = acont; +} + +template<class T> +inline const T & INDEX_3_CLOSED_HASHTABLE<T> :: +Get (const INDEX_3 & ahash) const +{ + int pos = Position (ahash); + return cont[pos]; +} + +template<class T> +inline bool INDEX_3_CLOSED_HASHTABLE<T> :: +Used (const INDEX_3 & ahash) const +{ + int pos = Position (ahash); + return (pos != 0); +} + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +SetData (int pos, const INDEX_3 & ahash, const T & acont) +{ + hash.Elem(pos) = ahash; + cont.Elem(pos) = acont; +} + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +GetData (int pos, INDEX_3 & ahash, T & acont) const +{ + ahash = hash.Get(pos); + acont = cont.Get(pos); +} + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +SetData (int pos, const T & acont) +{ + cont.Elem(pos) = acont; +} + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +GetData (int pos, T & acont) const +{ + acont = cont.Get(pos); +} + +template<class T> +inline const T & INDEX_3_CLOSED_HASHTABLE<T> :: +GetData (int pos) const +{ + return cont.Get(pos); +} + + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +SetSize (int size) +{ + BaseSetSize(size); + cont.SetSize(size); +} + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +PrintMemInfo (ostream & ost) const +{ + cout << "Hashtable: " << Size() + << " entries of size " << sizeof(INDEX_3) << " + " << sizeof(T) + << " = " << Size() * (sizeof(INDEX_3) + sizeof(T)) << " bytes" << endl; +} +*/ + + +} + + +#endif diff --git a/contrib/Netgen/libsrc/general/mpi_interface.hpp b/contrib/Netgen/libsrc/general/mpi_interface.hpp new file mode 100644 index 0000000000..53f2257946 --- /dev/null +++ b/contrib/Netgen/libsrc/general/mpi_interface.hpp @@ -0,0 +1,300 @@ +#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 +{ + + extern DLL_HEADER int id, ntasks; + + +#ifdef PARALLEL + + enum { MPI_TAG_CMD = 110 }; + enum { MPI_TAG_MESH = 210 }; + enum { MPI_TAG_VIS = 310 }; + + extern MPI_Comm mesh_comm; + + template <class T> + MPI_Datatype MyGetMPIType ( ) { cerr << "ERROR in GetMPIType() -- no type found" << endl;return 0;} + + template <> + inline MPI_Datatype MyGetMPIType<int> ( ) + { return MPI_INT; } + + template <> + inline MPI_Datatype MyGetMPIType<double> ( ) + { return MPI_DOUBLE; } + + + template <int S> class Vec; + template <> + inline MPI_Datatype MyGetMPIType<Vec<3> > () + { + 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; + }; + + + inline void MyMPI_Send (int i, int dest, int tag) + { + int hi = i; + MPI_Send( &hi, 1, MPI_INT, dest, tag, MPI_COMM_WORLD); + } + + inline void MyMPI_Recv (int & i, int src, int tag) + { + MPI_Status status; + MPI_Recv( &i, 1, MPI_INT, src, tag, MPI_COMM_WORLD, &status); + } + + + + inline void MyMPI_Send (const string & s, int dest, int tag) + { + MPI_Send( const_cast<char*> (s.c_str()), s.length(), MPI_CHAR, dest, tag, MPI_COMM_WORLD); + } + + inline void MyMPI_Recv (string & s, int src, int tag) + { + 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, MPI_COMM_WORLD, &status); + } + + + + + template <class T, int BASE> + inline void MyMPI_Send (FlatArray<T, BASE> s, int dest, int tag) + { + MPI_Send( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, MPI_COMM_WORLD); + } + + template <class T, int BASE> + inline void MyMPI_Recv ( FlatArray<T, BASE> s, int src, int tag) + { + MPI_Status status; + MPI_Recv( &s.First(), s.Size(), MyGetMPIType<T>(), src, tag, MPI_COMM_WORLD, &status); + } + + template <class T, int BASE> + inline void MyMPI_Recv ( Array <T, BASE> & s, int src, int tag) + { + MPI_Status status; + int len; + MPI_Probe (src, tag, MPI_COMM_WORLD, &status); + MPI_Get_count (&status, MyGetMPIType<T>(), &len); + + s.SetSize (len); + MPI_Recv( &s.First(), len, MyGetMPIType<T>(), src, tag, MPI_COMM_WORLD, &status); + } + + template <class T, int BASE> + inline int MyMPI_Recv ( Array <T, BASE> & s, int tag) + { + MPI_Status status; + int len; + MPI_Probe (MPI_ANY_SOURCE, tag, MPI_COMM_WORLD, &status); + + int src = status.MPI_SOURCE; + + MPI_Get_count (&status, MyGetMPIType<T>(), &len); + + s.SetSize (len); + MPI_Recv( &s.First(), len, MyGetMPIType<T>(), src, tag, MPI_COMM_WORLD, &status); + + return src; + } + + + /* + template <class T, int BASE> + inline void MyMPI_ISend (FlatArray<T, BASE> s, int dest, int tag, MPI_Request & request) + { + MPI_Isend( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, MPI_COMM_WORLD, & request); + } + + + template <class T, int BASE> + inline void MyMPI_IRecv (FlatArray<T, BASE> s, int dest, int tag, MPI_Request & request) + { + MPI_Irecv( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, MPI_COMM_WORLD, & request); + } + */ + + template <class T, int BASE> + inline MPI_Request MyMPI_ISend (FlatArray<T, BASE> s, int dest, int tag, MPI_Comm comm = MPI_COMM_WORLD) + { + MPI_Request request; + MPI_Isend( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, comm, &request); + return request; + } + + + template <class T, int BASE> + inline MPI_Request MyMPI_IRecv (FlatArray<T, BASE> s, int dest, int tag, MPI_Comm comm = MPI_COMM_WORLD) + { + MPI_Request request; + MPI_Irecv( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, comm, &request); + return request; + } + + /* + template <class T, int BASE> + inline void MyMPI_ISend (FlatArray<T, BASE> s, int dest, int tag) + { + MPI_Request request; + MPI_Isend( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, MPI_COMM_WORLD, &request); + MPI_Request_free (&request); + } + + + template <class T, int BASE> + inline void MyMPI_IRecv (FlatArray<T, BASE> s, int dest, int tag) + { + MPI_Request request; + MPI_Irecv( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, MPI_COMM_WORLD, &request); + MPI_Request_free (&request); + } + */ + + inline void MyMPI_SendCmd (const char * cmd) + { + char buf[100]; + strcpy (buf, cmd); + // MPI_Bcast (&buf, 100, MPI_CHAR, 0, MPI_COMM_WORLD); + + for (int dest = 1; dest < ntasks; dest++) + MPI_Bsend( &buf, 100, MPI_CHAR, dest, MPI_TAG_CMD, MPI_COMM_WORLD); + } + + inline string MyMPI_RecvCmd () + { + char buf[100]; + // MPI_Bcast (&buf, 100, MPI_CHAR, 0, MPI_COMM_WORLD); + + MPI_Status status; + int flag; + do + { + MPI_Iprobe (0, MPI_TAG_CMD, MPI_COMM_WORLD, &flag, &status); + if (!flag) usleep (1000); + } + while (!flag); + MPI_Recv( &buf, 100, MPI_CHAR, 0, MPI_TAG_CMD, MPI_COMM_WORLD, &status); + + return string(buf); + } + + template <class T> + inline void MyMPI_Bcast (T & s, MPI_Comm comm = MPI_COMM_WORLD) + { + MPI_Bcast (&s, 1, MyGetMPIType<T>(), 0, comm); + } + + template <class T> + inline void MyMPI_Bcast (Array<T, 0> & s, MPI_Comm comm = MPI_COMM_WORLD) + { + int size = s.Size(); + MyMPI_Bcast (size, comm); + if (id != 0) s.SetSize (size); + MPI_Bcast (&s[0], size, MyGetMPIType<T>(), 0, comm); + } + + template <class T> + inline void MyMPI_Bcast (Array<T, 0> & s, int root, MPI_Comm comm = MPI_COMM_WORLD) + { + 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<T>(), root, comm); + } + + template <class T, class T2> + inline void MyMPI_Allgather (const T & send, FlatArray<T2> recv, MPI_Comm comm) + { + MPI_Allgather( const_cast<T*> (&send), 1, MyGetMPIType<T>(), &recv[0], 1, MyGetMPIType<T2>(), comm); + } + + template <class T, class T2> + inline void MyMPI_Alltoall (FlatArray<T> send, FlatArray<T2> recv, MPI_Comm comm) + { + MPI_Alltoall( &send[0], 1, MyGetMPIType<T>(), &recv[0], 1, MyGetMPIType<T2>(), comm); + } + +// template <class T, class T2> +// inline void MyMPI_Alltoall_Block (FlatArray<T> send, FlatArray<T2> recv, int blocklen, MPI_Comm comm) +// { +// MPI_Alltoall( &send[0], blocklen, MyGetMPIType<T>(), &recv[0], blocklen, MyGetMPIType<T2>(), 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 diff --git a/contrib/Netgen/libsrc/general/myadt.hpp b/contrib/Netgen/libsrc/general/myadt.hpp new file mode 100644 index 0000000000..100e7a3a0b --- /dev/null +++ b/contrib/Netgen/libsrc/general/myadt.hpp @@ -0,0 +1,48 @@ +#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 "ngexception.hpp" +#include "parthreads.hpp" +// #include "moveablemem.hpp" +#include "dynamicmem.hpp" + +#include "template.hpp" +#include "array.hpp" +#include "table.hpp" +#include "hashtabl.hpp" + + +#include "symbolta.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 "profiler.hpp" + +#include "mpi_interface.hpp" +#include "netgenout.hpp" + + +#endif diff --git a/contrib/Netgen/libsrc/general/mystring.cpp b/contrib/Netgen/libsrc/general/mystring.cpp new file mode 100644 index 0000000000..dc59c80ee3 --- /dev/null +++ b/contrib/Netgen/libsrc/general/mystring.cpp @@ -0,0 +1,426 @@ + +//************************************************************** +// +// filename: mystring.cpp +// +// project: doctoral thesis +// +// autor: Dipl.-Ing. Gerstmayr Johannes +// +// generated: 20.12.98 +// last change: 20.12.98 +// description: implementation for strings +// remarks: +// +//************************************************************** + +// string class +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <gprim.hpp> + + +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(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(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 +*/ +} diff --git a/contrib/Netgen/libsrc/general/mystring.hpp b/contrib/Netgen/libsrc/general/mystring.hpp new file mode 100644 index 0000000000..49cc7001fa --- /dev/null +++ b/contrib/Netgen/libsrc/general/mystring.hpp @@ -0,0 +1,220 @@ + +//************************************************************** +// +// filename: mystring.h +// +// project: doctoral thesis, program smart +// +// autor: 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; + +MyStr operator + (const MyStr &, const MyStr &); +int operator == (const MyStr &, const MyStr &); +int operator < (const MyStr &, const MyStr &); +int operator <= (const MyStr &, const MyStr &); +int operator > (const MyStr &, const MyStr &); +int operator >= (const MyStr &, const MyStr &); +int operator != (const MyStr &, const MyStr &); +ostream& operator << (ostream &, const MyStr &); +istream& operator >> (istream &, MyStr &); + +class MyStr +{ +public: + DLL_HEADER MyStr(); + DLL_HEADER MyStr(const char *); + DLL_HEADER MyStr(char); + DLL_HEADER MyStr(const MyStr &); + DLL_HEADER MyStr(int); + DLL_HEADER MyStr(void *); + DLL_HEADER MyStr(long); + DLL_HEADER MyStr(double); + DLL_HEADER MyStr(const Point3d& p); + DLL_HEADER MyStr(const Vec3d& p); + DLL_HEADER 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 &); + 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; + + friend int operator == (const MyStr &, const MyStr &); + friend int operator < (const MyStr &, const MyStr &); + friend int operator <= (const MyStr &, const MyStr &); + friend int operator > (const MyStr &, const MyStr &); + friend int operator >= (const MyStr &, const MyStr &); + friend int operator != (const MyStr &, const MyStr &); + friend ostream& operator << (ostream &, const MyStr &); + 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 + + diff --git a/contrib/Netgen/libsrc/general/netgenout.hpp b/contrib/Netgen/libsrc/general/netgenout.hpp new file mode 100644 index 0000000000..06b23c22d5 --- /dev/null +++ b/contrib/Netgen/libsrc/general/netgenout.hpp @@ -0,0 +1,187 @@ +#ifndef NETGEN_OUT_STREAM_HPP__ +#define NETGEN_OUT_STREAM_HPP__ + +// #include <ostream> +// #include <mystdlib.h> +// #include <meshing.hpp> + +namespace netgen +{ + +#ifdef PARALLEL +extern int id; +extern int ntasks; +#endif +DLL_HEADER extern int printmessage_importance; + + + +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<int> procs; + +public: + + Procs ( const netgen::FlatArray<int> & aprocs ) : procs (aprocs) { ; } + + const netgen::FlatArray<int> & 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 <typename T> + 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 ); +// { +// return ( NetgenOutStream ( &ost, imp.GetImp() ) ); +// } + +// template <typename T> +// NetgenOutStream& operator<< (NetgenOutStream& out, T c ) +// { +// out.OStream() << c << endl; +// return out; +// } + + +} + + +#endif diff --git a/contrib/Netgen/libsrc/general/ngexception.cpp b/contrib/Netgen/libsrc/general/ngexception.cpp new file mode 100644 index 0000000000..2496f6b3be --- /dev/null +++ b/contrib/Netgen/libsrc/general/ngexception.cpp @@ -0,0 +1,33 @@ +/**************************************************************************/ +/* File: ngexception.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 16. Jan. 02 */ +/**************************************************************************/ + +#include <myadt.hpp> + +namespace netgen +{ + //using namespace netgen; + + + + NgException :: NgException (const string & s) + : what(s) + { + ; + } + + + NgException :: ~NgException () + { + ; + } + + /// append string to description + void NgException :: Append (const string & s) + { + what += s; + } + +} diff --git a/contrib/Netgen/libsrc/general/ngexception.hpp b/contrib/Netgen/libsrc/general/ngexception.hpp new file mode 100644 index 0000000000..70dc0a4a5d --- /dev/null +++ b/contrib/Netgen/libsrc/general/ngexception.hpp @@ -0,0 +1,33 @@ +#ifndef FILE_NGEXCEPTION +#define FILE_NGEXCEPTION + +/**************************************************************************/ +/* File: ngexception.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 16. Jan. 2002 */ +/**************************************************************************/ + +namespace netgen +{ + +/// Base class for all ng exceptions +class NgException +{ + /// verbal description of exception + string what; +public: + /// + DLL_HEADER NgException (const string & s); + /// + DLL_HEADER virtual ~NgException (); + + /// append string to description + DLL_HEADER void Append (const string & s); + // void Append (const char * s); + + /// verbal description of exception + const string & What() const { return what; } +}; +} + +#endif diff --git a/contrib/Netgen/libsrc/general/optmem.cpp b/contrib/Netgen/libsrc/general/optmem.cpp new file mode 100644 index 0000000000..adb4b36e99 --- /dev/null +++ b/contrib/Netgen/libsrc/general/optmem.cpp @@ -0,0 +1,63 @@ +/**************************************************************************/ +/* File: optmem.cc */ +/* Author: Joachim Schoeberl */ +/* Date: 04. Apr. 97 */ +/**************************************************************************/ + +/* + Abstract data type Array +*/ + + +#include <mystdlib.h> +#include <myadt.hpp> + +namespace netgen +{ + //using namespace netgen; + + BlockAllocator :: BlockAllocator (unsigned asize, unsigned ablocks) + : bablocks (0) + { + if (asize < sizeof(void*)) + asize = sizeof(void*); + size = asize; + blocks = ablocks; + freelist = NULL; + } + + BlockAllocator :: ~BlockAllocator () + { + for (int i = 0; i < bablocks.Size(); i++) + delete [] bablocks[i]; + } + + void * BlockAllocator :: Alloc () + { + // 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; + } + + void * p = freelist; + freelist = *(void**)freelist; + return p; + } + + /* + void BlockAllocator :: Free (void * p) + { + *(void**)p = freelist; + freelist = p; + } + */ +} diff --git a/contrib/Netgen/libsrc/general/optmem.hpp b/contrib/Netgen/libsrc/general/optmem.hpp new file mode 100644 index 0000000000..cd55f16ea5 --- /dev/null +++ b/contrib/Netgen/libsrc/general/optmem.hpp @@ -0,0 +1,62 @@ +#ifndef FILE_OPTMEM +#define FILE_OPTMEM + +/**************************************************************************/ +/* File: optmem.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 04. Apr. 97 */ +/**************************************************************************/ + +namespace netgen +{ + +/** + Optimized Memory allocation classes +*/ + +class BlockAllocator +{ +private: + /// + unsigned size, blocks; + /// + void * freelist; + /// + Array<char*> bablocks; +public: + /// + BlockAllocator (unsigned asize, unsigned ablocks = 100); + /// + ~BlockAllocator (); + /// + + void * Alloc (); + /* + { + if (!freelist) + Alloc2(); + + void * p = freelist; + // freelist = *(void**)freelist; + freelist = *static_cast<void**> (freelist); + + return p; + } + */ + + + /// + void Free (void * p) + { + *(void**)p = freelist; + freelist = p; + } + + +private: + // void Alloc2 (); +}; + +} + +#endif diff --git a/contrib/Netgen/libsrc/general/parthreads.cpp b/contrib/Netgen/libsrc/general/parthreads.cpp new file mode 100644 index 0000000000..81e9d0b6cc --- /dev/null +++ b/contrib/Netgen/libsrc/general/parthreads.cpp @@ -0,0 +1,40 @@ +/**************************************************************************/ +/* File: parthreads.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + + +#include <mystdlib.h> +#include <myadt.hpp> + +/* + +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 +} + +*/ diff --git a/contrib/Netgen/libsrc/general/parthreads.hpp b/contrib/Netgen/libsrc/general/parthreads.hpp new file mode 100644 index 0000000000..c103790955 --- /dev/null +++ b/contrib/Netgen/libsrc/general/parthreads.hpp @@ -0,0 +1,192 @@ +#ifndef FILE_PARTHREADS +#define FILE_PARTHREADS + +/**************************************************************************/ +/* File: parthreads.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 22. Nov. 2000 */ +/**************************************************************************/ + +/* + Parallel thread, Mutex, +*/ + +namespace netgen +{ + +#ifdef NO_PARALLEL_THREADS + +class NgMutex { }; + +class NgLock +{ +public: + NgLock (NgMutex & mut, bool lock = 0) { ; } + void Lock () { ; } + void UnLock () { ; } +}; + + +#else + +#ifdef _MSC_VER + +#ifdef MSVC_EXPRESS +// #include <pthread.h> + + +class NgMutex +{ + pthread_mutex_t mut; +public: + NgMutex () + { + pthread_mutex_init (&mut, NULL); + } + friend class NgLock; +}; + +class NgLock +{ + pthread_mutex_t & mut; + bool locked; +public: + NgLock (NgMutex & ngmut, bool lock = false) + : mut (ngmut.mut) + { + if (lock) + pthread_mutex_lock (&mut); + + locked = lock; + }; + + ~NgLock() + { + if (locked) + pthread_mutex_unlock (&mut); + } + + void Lock () + { + pthread_mutex_lock (&mut); + locked = true; + } + void UnLock () + { + pthread_mutex_unlock (&mut); + locked = false; + } + /* + int TryLock () + { + return pthread_mutex_trylock (&mut); + } + */ +}; + +#else // Using MS VC++ Standard / Enterprise / Professional edition... + + +class NgMutex +{ + CCriticalSection cs; + +public: + NgMutex () + { ; } + friend class NgLock; +}; + +class NgLock +{ + CSingleLock sl; + bool locked; +public: + NgLock (NgMutex & mut, bool lock = 0) + : sl(&mut.cs) + { + if (lock) sl.Lock(); + locked = lock; + } + + ~NgLock () + { + if (locked) sl.Unlock(); + } + + void Lock () + { + sl.Lock(); + locked = 1; + } + + void UnLock () + { + sl.Unlock(); + locked = 0; + } +}; + +#endif // MSVC_EXPRESS + +#else + + +// #include <pthread.h> + +class NgMutex +{ + pthread_mutex_t mut; +public: + NgMutex () + { + pthread_mutex_init (&mut, NULL); + } + friend class NgLock; +}; + +class NgLock +{ + pthread_mutex_t & mut; + bool locked; +public: + NgLock (NgMutex & ngmut, bool lock = false) + : mut (ngmut.mut) + { + if (lock) + pthread_mutex_lock (&mut); + + locked = lock; + }; + + ~NgLock() + { + if (locked) + pthread_mutex_unlock (&mut); + } + + void Lock () + { + pthread_mutex_lock (&mut); + locked = true; + } + void UnLock () + { + pthread_mutex_unlock (&mut); + locked = false; + } + /* + int TryLock () + { + return pthread_mutex_trylock (&mut); + } + */ +}; + +#endif + +#endif + +} + +#endif diff --git a/contrib/Netgen/libsrc/general/profiler.cpp b/contrib/Netgen/libsrc/general/profiler.cpp new file mode 100644 index 0000000000..91db4effd3 --- /dev/null +++ b/contrib/Netgen/libsrc/general/profiler.cpp @@ -0,0 +1,118 @@ +/**************************************************************************/ +/* File: profiler.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 19. Apr. 2002 */ +/**************************************************************************/ + + +#include <myadt.hpp> + +namespace netgen +{ + //using namespace netgen; + + long int NgProfiler::tottimes[SIZE]; + long int NgProfiler::starttimes[SIZE]; + long int NgProfiler::counts[SIZE]; + string NgProfiler::names[SIZE]; + int NgProfiler::usedcounter[SIZE]; + + + NgProfiler :: NgProfiler() + { + for (int i = 0; i < SIZE; i++) + { + tottimes[i] = 0; + usedcounter[i] = 0; + } + + total_timer = CreateTimer ("total CPU time"); + StartTimer (total_timer); + } + + NgProfiler :: ~NgProfiler() + { +#ifndef PARALLEL + StopTimer (total_timer); +#endif + + //ofstream prof; + //prof.open("ng.prof"); + + // ofstream-constructor may be called after STL-stuff is destructed, + // which leads to an "order of destruction"-problem, + // thus we use the C-variant: + + if (getenv ("NGPROFILE")) + { + char filename[100]; +#ifdef PARALLEL + sprintf (filename, "netgen.prof.%d", id); +#else + sprintf (filename, "netgen.prof"); +#endif + + if (id == 0) printf ("write profile to file netgen.prof\n"); + FILE *prof = fopen(filename,"w"); + Print (prof); + fclose(prof); + } + } + + +// void NgProfiler :: Print (ostream & prof) +// { +// for (int i = 0; i < SIZE; i++) +// if (counts[i] != 0 || usedcounter[i] != 0) +// { +// prof.setf (ios::fixed, ios::floatfield); +// prof.setf (ios::showpoint); + +// prof // << "job " << setw(3) << i +// << "calls " << setw(8) << counts[i] +// << ", time " << setprecision(2) << setw(6) << double(tottimes[i]) / CLOCKS_PER_SEC << " sec"; + +// if (usedcounter[i]) +// prof << " " << names[i]; +// else +// prof << " " << i; + +// prof << endl; +// } +// } + + + void NgProfiler :: Print (FILE * prof) + { + for (int i = 0; i < SIZE; i++) + if (counts[i] != 0 || usedcounter[i] != 0) + { + //fprintf(prof,"job %3i calls %8i, time %6.2f sec",i,counts[i],double(tottimes[i]) / CLOCKS_PER_SEC); + fprintf(prof,"calls %8li, time %6.2f sec",counts[i],double(tottimes[i]) / CLOCKS_PER_SEC); + if(usedcounter[i]) + fprintf(prof," %s",names[i].c_str()); + else + fprintf(prof," %i",i); + fprintf(prof,"\n"); + } + } + + int NgProfiler :: CreateTimer (const string & name) + { + for (int i = SIZE-1; i > 0; i--) + if(names[i] == name) + return i; + + for (int i = SIZE-1; i > 0; i--) + if (!usedcounter[i]) + { + usedcounter[i] = 1; + names[i] = name; + return i; + } + return -1; + } + + + NgProfiler prof; +} diff --git a/contrib/Netgen/libsrc/general/profiler.hpp b/contrib/Netgen/libsrc/general/profiler.hpp new file mode 100644 index 0000000000..a3ad811c5a --- /dev/null +++ b/contrib/Netgen/libsrc/general/profiler.hpp @@ -0,0 +1,66 @@ +#ifndef FILE_NG_PROFILER +#define FILE_NG_PROFILER + +/**************************************************************************/ +/* File: profiler.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 5. Jan. 2005 */ +/**************************************************************************/ + + + +#ifdef VTRACE +#include "vt_user.h" +#else + #define VT_USER_START(n) + #define VT_USER_END(n) + #define VT_TRACER(n) +#endif + +namespace netgen +{ + +class NgProfiler +{ + enum { SIZE = 1000 }; + + static long int tottimes[SIZE]; + static long int starttimes[SIZE]; + static long int counts[SIZE]; + static string names[SIZE]; + static int usedcounter[SIZE]; + + int total_timer; +public: + NgProfiler(); + ~NgProfiler(); + static int CreateTimer (const string & name); + + static void StartTimer (int nr) + { + starttimes[nr] = clock(); counts[nr]++; + // VT_USER_START (const_cast<char*> (names[nr].c_str())); + VT_USER_START ( (char * const) (names[nr].c_str())); + } + static void StopTimer (int nr) + { + tottimes[nr] += clock()-starttimes[nr]; + VT_USER_END (const_cast<char*> (names[nr].c_str())); + } + + //static void Print (ostream & ost); + static void Print (FILE * prof); + + class RegionTimer + { + int nr; + public: + RegionTimer (int anr) : nr(anr) + { StartTimer (nr); } + ~RegionTimer () { StopTimer (nr); } + }; +}; + +} + +#endif diff --git a/contrib/Netgen/libsrc/general/seti.cpp b/contrib/Netgen/libsrc/general/seti.cpp new file mode 100644 index 0000000000..e7f5b2ea74 --- /dev/null +++ b/contrib/Netgen/libsrc/general/seti.cpp @@ -0,0 +1,70 @@ +#include <mystdlib.h> +#include <myadt.hpp> + + +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); + } +} diff --git a/contrib/Netgen/libsrc/general/seti.hpp b/contrib/Netgen/libsrc/general/seti.hpp new file mode 100644 index 0000000000..4adbb09c57 --- /dev/null +++ b/contrib/Netgen/libsrc/general/seti.hpp @@ -0,0 +1,50 @@ +#ifndef FILE_SETI +#define FILE_SETI + + +/**************************************************************************/ +/* File: seti.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Mar. 98 */ +/**************************************************************************/ + +namespace netgen +{ + +/** + Set of Integers + */ +class IndexSet +{ + Array<int> 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<int> & GetArray() { return set; } +}; + +} + +#endif + diff --git a/contrib/Netgen/libsrc/general/sort.cpp b/contrib/Netgen/libsrc/general/sort.cpp new file mode 100644 index 0000000000..a6adda1a04 --- /dev/null +++ b/contrib/Netgen/libsrc/general/sort.cpp @@ -0,0 +1,75 @@ +/**************************************************************************/ +/* File: sort.cc */ +/* Author: Joachim Schoeberl */ +/* Date: 07. Jan. 00 */ +/**************************************************************************/ + +/* + Sorting +*/ + + +#include <algorithm> +#include <mystdlib.h> +#include <myadt.hpp> + +namespace netgen +{ + + void Sort (const Array<double> & values, + Array<int> & 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<double> & values, + Array<int> & 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<double> & values, + Array<int> & 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()); + } +} diff --git a/contrib/Netgen/libsrc/general/sort.hpp b/contrib/Netgen/libsrc/general/sort.hpp new file mode 100644 index 0000000000..3a9b41db9f --- /dev/null +++ b/contrib/Netgen/libsrc/general/sort.hpp @@ -0,0 +1,46 @@ +#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<double> & values, + Array<int> & order); + +extern void QuickSort (const Array<double> & values, + Array<int> & order); + + + + +template <class T> +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 <class T> +inline void BubbleSort (Array<T> & data) +{ + if(data.Size() > 0) + BubbleSort (data.Size(), &data[data.Begin()]); +} + +} + +#endif diff --git a/contrib/Netgen/libsrc/general/spbita2d.cpp b/contrib/Netgen/libsrc/general/spbita2d.cpp new file mode 100644 index 0000000000..45e8641370 --- /dev/null +++ b/contrib/Netgen/libsrc/general/spbita2d.cpp @@ -0,0 +1,172 @@ +/**************************************************************************/ +/* File: spbita2d.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + Implementation of sparse 2 dimensional bitarray +*/ + + +#include <mystdlib.h> +#include <myadt.hpp> + +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"); + } + } + } + +} diff --git a/contrib/Netgen/libsrc/general/spbita2d.hpp b/contrib/Netgen/libsrc/general/spbita2d.hpp new file mode 100644 index 0000000000..ba451fc789 --- /dev/null +++ b/contrib/Netgen/libsrc/general/spbita2d.hpp @@ -0,0 +1,59 @@ +#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 diff --git a/contrib/Netgen/libsrc/general/stack.hpp b/contrib/Netgen/libsrc/general/stack.hpp new file mode 100644 index 0000000000..83adee640c --- /dev/null +++ b/contrib/Netgen/libsrc/general/stack.hpp @@ -0,0 +1,114 @@ +#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 T> 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<T> elems; + /// + INDEX size; +}; + + + + +/* + + Stack class, based on a resizable array + + */ + +template <class T> +inline STACK<T> :: STACK (INDEX asize, INDEX ainc) + : elems(asize, ainc) +{ + size = 0; +} + + +template <class T> +inline STACK<T> :: ~STACK () +{ + ; +} + + +template <class T> +inline void STACK<T> :: Push (const T & el) +{ + if (size < elems.Size()) + elems.Elem(++size) = el; + else + { + elems.Append(el); + size++; + } +} + + +template <class T> +inline T & STACK<T> :: Pop () +{ + return elems.Elem(size--); +} + + +template <class T> +const inline T & STACK<T> :: Top () const +{ + return elems.Get(size); +} + +template <class T> +inline int STACK<T> :: IsEmpty () const +{ + return (size == 0); +} + + +template <class T> +inline void STACK<T> :: MakeEmpty () +{ + size = 0; +} + +} + +#endif diff --git a/contrib/Netgen/libsrc/general/symbolta.cpp b/contrib/Netgen/libsrc/general/symbolta.cpp new file mode 100644 index 0000000000..bd35ac7cb2 --- /dev/null +++ b/contrib/Netgen/libsrc/general/symbolta.cpp @@ -0,0 +1,52 @@ +/**************************************************************************/ +/* File: symbolta.cc */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + Abstract data type Symbol Table +*/ + +#include <mystdlib.h> +#include <myadt.hpp> + + +#ifndef FILE_SYMBOLTABLECC +#define FILE_SYMBOLTABLECC +// necessary for SGI ???? + + +namespace netgen +{ + //using namespace netgen; + + BASE_SYMBOLTABLE :: BASE_SYMBOLTABLE () + { + ; + } + + + BASE_SYMBOLTABLE :: ~BASE_SYMBOLTABLE() + { + DelNames(); + } + + + void BASE_SYMBOLTABLE :: DelNames() + { + for (int i = 0; i < names.Size(); i++) + delete [] names[i]; + names.SetSize (0); + } + + int BASE_SYMBOLTABLE :: Index (const char * name) const + { + if (!name) return 0; + for (int i = 0; i < names.Size(); i++) + if (strcmp (names[i], name) == 0) return i+1; + return 0; + } +} + +#endif diff --git a/contrib/Netgen/libsrc/general/symbolta.hpp b/contrib/Netgen/libsrc/general/symbolta.hpp new file mode 100644 index 0000000000..cfb6d9574b --- /dev/null +++ b/contrib/Netgen/libsrc/general/symbolta.hpp @@ -0,0 +1,161 @@ +#ifndef FILE_SYMBOLTA +#define FILE_SYMBOLTA + + +/**************************************************************************/ +/* File: symbolta.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +namespace netgen +{ + +/** + Base class for the generic SYMBOLTABLE. + An array of identifiers is maintained. +*/ +class BASE_SYMBOLTABLE +{ +protected: + /// identifiers + Array <char*> names; + +public: + /// Constructor + BASE_SYMBOLTABLE (); + /// + ~BASE_SYMBOLTABLE (); + /// + void DelNames (); + /// Index of symbol name, returns 0 if not used. + int Index (const char * name) const; +}; + + +/** + Abstract data type Symbol Table. + + To a string an value of the generic type T is associated. + The string is not copied into the symbol table class! +*/ +template <class T> +class SYMBOLTABLE : public BASE_SYMBOLTABLE +{ +private: + /// Associated data + Array <T> data; + +public: + /// Creates a symboltable + inline SYMBOLTABLE (); + /// Returns size of symboltable + inline INDEX Size() const; + /// Returns reference to element, error if not used + inline T & Elem (const char * name); + /// Returns reference to i-th element + inline T & Elem (int i) + { return data.Elem(i); } + /// Returns element, error if not used + inline const T & Get (const char * name) const; + /// Returns i-th element + inline const T & Get (int i) const; + /// Returns name of i-th element + inline const char* GetName (int i) const; + /// Associates el to the string name, overrides if name is used + inline void Set (const char * name, const T & el); + /// Checks whether name is used + inline bool Used (const char * name) const; + /// Deletes symboltable + inline void DeleteAll (); + + inline T & operator[] (int i) + { return data[i]; } + inline const T & operator[] (int i) const + { return data[i]; } + +private: + /// Prevents from copying symboltable by pointer assignment + SYMBOLTABLE<T> & operator= (SYMBOLTABLE<T> &); +}; + + + + +template <class T> +inline SYMBOLTABLE<T> :: SYMBOLTABLE () +{ + ; +} + + +template <class T> +inline INDEX SYMBOLTABLE<T> :: Size() const +{ + return data.Size(); +} + +template <class T> +inline T & SYMBOLTABLE<T> :: Elem (const char * name) +{ + int i = Index (name); + if (i) + return data.Elem (i); + else + return data.Elem(1); +} + +template <class T> +inline const T & SYMBOLTABLE<T> :: Get (const char * name) const +{ + int i; + i = Index (name); + if (i) + return data.Get(i); + else + return data.Get(1); +} + +template <class T> +inline const T & SYMBOLTABLE<T> :: Get (int i) const +{ + return data.Get(i); +} + +template <class T> +inline const char* SYMBOLTABLE<T> :: GetName (int i) const +{ + return names.Get(i); +} + +template <class T> +inline void SYMBOLTABLE<T> :: Set (const char * name, const T & el) +{ + int i; + i = Index (name); + if (i) + data.Set(i, el); + else + { + data.Append (el); + char * hname = new char [strlen (name) + 1]; + strcpy (hname, name); + names.Append (hname); + } +} + +template <class T> +inline bool SYMBOLTABLE<T> :: Used (const char * name) const +{ + return (Index(name)) ? true : false; +} + +template <class T> +inline void SYMBOLTABLE<T> :: DeleteAll () +{ + DelNames(); + data.DeleteAll(); +} + +} +#endif diff --git a/contrib/Netgen/libsrc/general/table.cpp b/contrib/Netgen/libsrc/general/table.cpp new file mode 100644 index 0000000000..d9d6cf139d --- /dev/null +++ b/contrib/Netgen/libsrc/general/table.cpp @@ -0,0 +1,214 @@ +/**************************************************************************/ +/* File: table.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + Abstract data type TABLE +*/ + +#include <mystdlib.h> +#include <myadt.hpp> + +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<int> & entrysizes, int elemsize) + : data(entrysizes.Size()) + { + int i, cnt = 0; + int n = entrysizes.Size(); + + for (i = 0; i < n; i++) + cnt += entrysizes[i]; + oneblock = new char[elemsize * cnt]; + // mem_total_alloc_table += elemsize * cnt; + + cnt = 0; + for (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) + { + int cnt = 0; + int n = data.Size(); + + for (int i = 0; i < n; i++) + cnt += data[i].maxsize; + oneblock = new char[elemsize * cnt]; + + cnt = 0; + for (int i = 0; i < n; i++) + { + data[i].size = 0; + data[i].col = &oneblock[elemsize * cnt]; + cnt += data[i].maxsize; + } + } + + + + int BASE_TABLE :: AllocatedElements () const + { + int els = 0; + for (int i = 0; i < data.Size(); i++) + els += data[i].maxsize; + return els; + } + + int BASE_TABLE :: UsedElements () const + { + int els = 0; + for (int 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; + } + +} diff --git a/contrib/Netgen/libsrc/general/table.hpp b/contrib/Netgen/libsrc/general/table.hpp new file mode 100644 index 0000000000..f63b80746a --- /dev/null +++ b/contrib/Netgen/libsrc/general/table.hpp @@ -0,0 +1,239 @@ +#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<linestruct> data; + char * oneblock; + +public: + /// + BASE_TABLE (int size); + /// + BASE_TABLE (const FlatArray<int> & entrysizes, int elemsize); + /// + ~BASE_TABLE (); + /// + 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); + + int AllocatedElements () const; + int UsedElements () const; + + void SetElementSizesToMaxSizes (); +}; + + + + + + + +/** + 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 T, int BASE = 0> +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<int,BASE> & entrysizes) + : BASE_TABLE (FlatArray<int> (entrysizes.Size(), const_cast<int*>(&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++; + } + + /// 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<T> 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<T> (data[i-BASE].size, (T*)data[i-BASE].col); + } +}; + + +template <class T, int BASE> +inline ostream & operator<< (ostream & ost, const TABLE<T,BASE> & table) +{ + for (int i = BASE; i < table.Size()+BASE; i++) + { + ost << i << ": "; + FlatArray<T> row = table[i]; + ost << "(" << row.Size() << ") "; + for (int j = 0; j < row.Size(); j++) + ost << row[j] << " "; + ost << endl; + } + return ost; +} + +} + +#endif + diff --git a/contrib/Netgen/libsrc/general/template.hpp b/contrib/Netgen/libsrc/general/template.hpp new file mode 100644 index 0000000000..0bb83f2732 --- /dev/null +++ b/contrib/Netgen/libsrc/general/template.hpp @@ -0,0 +1,460 @@ +#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 <iostream> +/** output stream for testing. + testout is opened by main */ +DLL_HEADER extern ostream * testout; + +/** use instead of cout */ +extern ostream * mycout; + +/** error output stream */ +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. */ +extern void MyBeep (int nr = 1); + + +template <class T> +inline void Swap (T & a, T & b) +{ + T temp = a; + a = b; + b = temp; +} + +/* +template <class T> +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); +}; + + +/// +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 <class T> +inline T min2 (T a, T b) +{ + /// + return (a < b) ? a : b; +} +/// +template <class T> +inline T max2 (T a, T b) +{ + /// + return (a > b) ? a : b; +} +/// +template <class T> +inline T min3 (T a, T b, T c) +{ + /// + return (a < b) ? (a < c) ? a : c + : (b < c) ? b : c; +} +/// +template <class T> +inline T max3 (T a, T b, T c) +{ + /// + return (a > b) ? ((a > c) ? a : c) + : ((b > c) ? b : c); +} + +/// + +/// +template <class T> +inline int sgn (T a) +{ + return (a > 0) ? 1 : ( ( a < 0) ? -1 : 0 ); +} + +/// +template <class T> +inline T sqr (const T a) +{ + return a * a; +} + +/// +template <class T> +inline T pow3 (const T a) +{ + return a * a * a; +} + + + +/* +template <class T> +void BubbleSort (int size, T * data); + +template <class T> +void MergeSort (int size, T * data, T * help); +*/ + + + +} + +#endif diff --git a/contrib/Netgen/libsrc/geom2d/Makefile.am b/contrib/Netgen/libsrc/geom2d/Makefile.am new file mode 100644 index 0000000000..82d95667b3 --- /dev/null +++ b/contrib/Netgen/libsrc/geom2d/Makefile.am @@ -0,0 +1,14 @@ +noinst_HEADERS = geom2dmesh.hpp geometry2d.hpp vsgeom2d.hpp + +AM_CPPFLAGS = -I$(top_srcdir)/libsrc/include $(TCL_INCLUDES) + +METASOURCES = AUTO +lib_LTLIBRARIES = libgeom2d.la libgeom2dvis.la + +libgeom2d_la_SOURCES = genmesh2d.cpp geom2dmesh.cpp geometry2d.cpp +libgeom2d_la_LIBADD = $(top_builddir)/libsrc/meshing/libmesh.la + +libgeom2dvis_la_SOURCES = geom2dpkg.cpp vsgeom2d.cpp +libgeom2dvis_la_LIBADD = libgeom2d.la + + diff --git a/contrib/Netgen/libsrc/geom2d/genmesh2d.cpp b/contrib/Netgen/libsrc/geom2d/genmesh2d.cpp new file mode 100644 index 0000000000..000e5ad67d --- /dev/null +++ b/contrib/Netgen/libsrc/geom2d/genmesh2d.cpp @@ -0,0 +1,542 @@ +#include <meshing.hpp> +#include <geometry2d.hpp> + +namespace netgen +{ + extern DLL_HEADER MeshingParameters mparam; + + extern void Optimize2d (Mesh & mesh, MeshingParameters & mp); + + + + void CalcPartition (double l, double h, double h1, double h2, + double hcurve, double elto0, Array<double> & points); + + // partitionizes spline curve + void Partition (const SplineSegExt & spline, + double h, double elto0, + Mesh & mesh, Point3dTree & searchtree, int segnr) + { + enum { D = 2 }; + int i, j; + double l; // , r1, r2, ra; + double lold, dt, frac; + int n = 100; + Point<D> p, pold, mark, oldmark; + Array<double> curvepoints; + double edgelength, edgelengthold; + l = spline.Length(); + + double h1 = min (spline.StartPI().hmax, h/spline.StartPI().refatpoint); + double h2 = min (spline.EndPI().hmax, h/spline.EndPI().refatpoint); + double hcurve = min (spline.hmax, h/spline.reffak); + + CalcPartition (l, h, h1, h2, hcurve, elto0, curvepoints); + // cout << "curvepoints = " << curvepoints << endl; + + dt = 1.0 / n; + + l = 0; + j = 1; + + pold = spline.GetPoint (0); + lold = 0; + oldmark = pold; + edgelengthold = 0; + Array<int> locsearch; + + for (i = 1; i <= n; i++) + { + p = spline.GetPoint (i*dt); + l = lold + Dist (p, pold); + while (j < curvepoints.Size() && (l >= curvepoints[j] || i == n)) + { + frac = (curvepoints[j]-lold) / (l-lold); + edgelength = i*dt + (frac-1)*dt; + // mark = pold + frac * (p-pold); + mark = spline.GetPoint (edgelength); + + // cout << "mark = " << mark << " =?= " << GetPoint (edgelength) << endl; + + { + PointIndex pi1 = -1, pi2 = -1; + + Point3d mark3(mark(0), mark(1), 0); + Point3d oldmark3(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]; + // if (locsearch.Size()) pi1 = locsearch[0]; + + 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 (locsearch.Size()) pi2 = locsearch[0]; + + /* + for (PointIndex pk = PointIndex::BASE; + pk < mesh.GetNP()+PointIndex::BASE; pk++) + { + if (Dist (mesh[pk], oldmark3) < 1e-4 * h) pi1 = pk; + if (Dist (mesh[pk], mark3) < 1e-4 * h) pi2 = pk; + } + */ + + + // cout << "pi1 = " << pi1 << endl; + // cout << "pi2 = " << pi2 << endl; + + 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 (double h, Mesh & mesh2d) + { + enum { D = 2 }; + Box<D> 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<D;j++) + { + pmin(j) = bbox.PMin()(j); + pmax(j) = bbox.PMax()(j); + } + + Point3dTree searchtree (pmin, pmax); + + for (int i = 0; i < splines.Size(); i++) + for (int side = 0; side <= 1; side++) + { + int dom = (side == 0) ? GetSpline(i).leftdom : GetSpline(i).rightdom; + if (dom != 0) GetSpline(i).layer = GetDomainLayer (dom); + } + + 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 minimum = min2 ( GetDomainMaxh ( GetSpline(i).leftdom ), GetDomainMaxh ( GetSpline(i).rightdom ) ); + double maximum = max2 ( GetDomainMaxh ( GetSpline(i).leftdom ), GetDomainMaxh ( GetSpline(i).rightdom ) ); + minimum = min2 ( minimum, h ); + maximum = min2 ( maximum, h); + if ( minimum > 0 ) + // GetSpline(i).Partition(minimum, elto0, mesh2d, searchtree, i+1); + Partition(GetSpline(i), minimum, elto0, mesh2d, searchtree, i+1); + else if ( maximum > 0 ) + // GetSpline(i).Partition(maximum, elto0, mesh2d, searchtree, i+1); + Partition(GetSpline(i), maximum, elto0, mesh2d, searchtree, i+1); + else + // GetSpline(i).Partition(h, elto0, mesh2d, searchtree, i+1); + Partition(GetSpline(i), h, 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; + int i; + + Array<int, PointIndex::BASE> mappoints (mesh.GetNP()); + Array<double, PointIndex::BASE> 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 (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 (i = 1; i <= mappoints.Size(); i++) + { + if (mappoints.Get(i) != -1) + { + Point<D> newp = splines.Get(to)->GetPoint (param.Get(i)); + Point<3> newp3; + for(int j=0; j<min2(D,3); j++) + newp3(j) = newp(j); + for(int j=min2(D,3); j<3; j++) + newp3(j) = 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 (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, + Mesh *& mesh, + MeshingParameters & mp) + { + PrintMessage (1, "Generate Mesh from spline geometry"); + + double h = mp.maxh; + + Box<2> bbox = geometry.GetBoundingBox (); + + if (bbox.Diam() < h) + { + h = bbox.Diam(); + mp.maxh = h; + } + + mesh = new Mesh; + mesh->SetDimension (2); + + geometry.PartitionBoundary (h, *mesh); + + + // 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(1.); + } + + + 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<string*> 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 ) ); + + Point3d pmin(bbox.PMin()(0), bbox.PMin()(1), -bbox.Diam()); + Point3d pmax(bbox.PMax()(0), bbox.PMax()(1), bbox.Diam()); + + mesh->SetLocalH (pmin, pmax, mparam.grading); + mesh->SetGlobalH (h); + + mesh->CalcLocalH(mparam.grading); + + int bnp = mesh->GetNP(); // boundary points + + int hquad = mparam.quad; + + + for (int domnr = 1; domnr <= maxdomnr; domnr++) + if (geometry.GetDomainTensorMeshing (domnr)) + { // tensor product mesh + + Array<PointIndex, PointIndex::BASE> nextpi(bnp); + Array<int, PointIndex::BASE> 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<PointIndex> 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; + + if ( geometry.GetDomainMaxh ( domnr ) > 0 ) + h = geometry.GetDomainMaxh(domnr); + + + PrintMessage (3, "Meshing domain ", domnr, " / ", maxdomnr); + + int oldnf = mesh->GetNSE(); + + mparam.quad = hquad || geometry.GetDomainQuadMeshing (domnr); + + Meshing2 meshing (mparam, Box<3> (pmin, pmax)); + + Array<int, PointIndex::BASE> compress(bnp); + compress = -1; + int cnt = 0; + for (PointIndex pi = PointIndex::BASE; pi < bnp+PointIndex::BASE; pi++) + 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); + + } + + } + + + mparam.checkoverlap = 0; + + /* + if (!mparam.quad) + meshing.Delaunay (*mesh, domnr, mparam); + else + */ + meshing.GenerateMesh (*mesh, mparam, h, domnr); + + 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 ); + } + + } + + mparam.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 -> SetNextMajorTimeStamp(); + + + extern DLL_HEADER void Render(); + Render(); + } + + + + + + + + +} diff --git a/contrib/Netgen/libsrc/geom2d/geom2dmesh.cpp b/contrib/Netgen/libsrc/geom2d/geom2dmesh.cpp new file mode 100644 index 0000000000..87472d21c9 --- /dev/null +++ b/contrib/Netgen/libsrc/geom2d/geom2dmesh.cpp @@ -0,0 +1,82 @@ +#include <meshing.hpp> +#include <geometry2d.hpp> + +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; + + p2d = geometry.GetSplines().Get(ap1.edgenr) -> + GetPoint (((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 = ((1-secpoint)*ap1.dist+secpoint*ap2.dist); + }; + + + + 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); + } +} diff --git a/contrib/Netgen/libsrc/geom2d/geom2dmesh.hpp b/contrib/Netgen/libsrc/geom2d/geom2dmesh.hpp new file mode 100644 index 0000000000..9b72216df3 --- /dev/null +++ b/contrib/Netgen/libsrc/geom2d/geom2dmesh.hpp @@ -0,0 +1,52 @@ +#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 diff --git a/contrib/Netgen/libsrc/geom2d/geom2dpkg.cpp b/contrib/Netgen/libsrc/geom2d/geom2dpkg.cpp new file mode 100644 index 0000000000..1456c6ac1d --- /dev/null +++ b/contrib/Netgen/libsrc/geom2d/geom2dpkg.cpp @@ -0,0 +1,72 @@ +#include <meshing.hpp> +#include <geometry2d.hpp> +#include <visual.hpp> + +#include "vsgeom2d.hpp" + +// extern "C" int Ng_CSG_Init (Tcl_Interp * interp); + +namespace netgen +{ + + + extern DLL_HEADER NetgenGeometry * ng_geometry; + static VisualSceneGeometry2d vsgeom2d; + + + + class SplineGeometryRegister : public GeometryRegister + { + public: + virtual NetgenGeometry * Load (string filename) const; + virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) 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; + } + + + + VisualScene * SplineGeometryRegister :: GetVisualScene (const NetgenGeometry * geom) const + { + SplineGeometry2d * geometry = dynamic_cast<SplineGeometry2d*> (ng_geometry); + 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 SplineGeometryRegister); + return TCL_OK; +} diff --git a/contrib/Netgen/libsrc/geom2d/geometry2d.cpp b/contrib/Netgen/libsrc/geom2d/geometry2d.cpp new file mode 100644 index 0000000000..e8b10c5ebc --- /dev/null +++ b/contrib/Netgen/libsrc/geom2d/geometry2d.cpp @@ -0,0 +1,938 @@ +/* + +2d Spline curve for Mesh generator + +*/ + +#include <meshing.hpp> +#include <geometry2d.hpp> + +namespace netgen +{ + + + + SplineGeometry2d :: ~SplineGeometry2d() + { + for ( int i = 0; i < bcnames.Size(); i++ ) + delete bcnames[i]; + for (int i=0; i<materials.Size(); i++) + delete materials[i]; + } + + + void SplineGeometry2d :: Load (const char * filename) + { + + ifstream infile; + Point<2> 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<D> 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<D; j++) + infile >> 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<D>(x, hd)); + geompoints.Last().hpref = flags.GetDefineFlag ("hpref"); + geompoints.Last().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<D> * 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 segement + if (strcmp (buf, "2") == 0) + { // a line + infile >> hi1 >> hi2; + spline = new LineSeg<D>(geompoints[hi1-1], + geompoints[hi2-1]); + } + else if (strcmp (buf, "3") == 0) + { // a rational spline + infile >> hi1 >> hi2 >> hi3; + spline = new SplineSeg3<D> (geompoints[hi1-1], + geompoints[hi2-1], + geompoints[hi3-1]); + } + else if (strcmp (buf, "4") == 0) + { // an arc + infile >> hi1 >> hi2 >> hi3; + spline = new CircleSeg<D> (geompoints[hi1-1], + geompoints[hi2-1], + geompoints[hi3-1]); + // break; + } + else if (strcmp (buf, "discretepoints") == 0) + { + int npts; + infile >> npts; + Array< Point<D> > pts(npts); + for (int j = 0; j < npts; j++) + for(int k=0; k<D; k++) + infile >> pts[j](k); + + spline = new DiscretePointsSeg<D> (pts); + } + + + SplineSegExt * spex = new SplineSegExt (*spline); + + infile >> spex->reffak; + spex -> leftdom = leftdom; + spex -> rightdom = rightdom; + spex -> hmax = 1e99; + 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","") ); + } + } + } + + + + + void SplineGeometry2d :: LoadDataNew ( ifstream & infile ) + { + enum { D = 2 }; + int nump, numseg, leftdom, rightdom; + Point<D> 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<D; j++) + infile >> 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<D>(x, hd)); + geompoints[pointnr-1] = GeomPoint<D>(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<D> * 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 segement + if (strcmp (buf, "2") == 0) + { // a line + infile >> hi1 >> hi2; + spline = new LineSeg<D> (geompoints[hi1-1], + geompoints[hi2-1]); + } + else if (strcmp (buf, "3") == 0) + { // a rational spline + infile >> hi1 >> hi2 >> hi3; + spline = new SplineSeg3<D> (geompoints[hi1-1], + geompoints[hi2-1], + geompoints[hi3-1]); + } + else if (strcmp (buf, "4") == 0) + { // an arc + infile >> hi1 >> hi2 >> hi3; + spline = new CircleSeg<D> (geompoints[hi1-1], + geompoints[hi2-1], + geompoints[hi3-1]); + // break; + } + else if (strcmp (buf, "discretepoints") == 0) + { + int npts; + infile >> npts; + Array< Point<D> > pts(npts); + for (int j = 0; j < npts; j++) + for(int k=0; k<D; k++) + infile >> pts[j](k); + + spline = new DiscretePointsSeg<D> (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 ) ; + for ( int i = 0; i < numdomains; i++) + maxh[i] = 1000; + + TestComment ( infile ); + + for ( int i=0; i<numdomains; i++) + materials [ i ] = new char (100); + + for ( int i=0; i<numdomains && infile.good(); i++) + { + TestComment ( infile ); + infile >> 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); + } + 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<D> x; + int hi1, hi2, hi3; + double hd; + char buf[50], ch; + int pointnr; + + string keyword; + + Array < GeomPoint<D> > infilepoints (0); + Array <int> 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<D; j++) + infile >> 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<D>(x, hd)); + + infilepoints.Append ( GeomPoint<D>(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<D> * spline = 0; + TestComment ( infile ); + + infile >> leftdom >> rightdom; + + if ( leftdom > numdomains ) numdomains = leftdom; + if ( rightdom > numdomains ) numdomains = rightdom; + + + infile >> buf; + // type of spline segement + if (strcmp (buf, "2") == 0) + { // a line + infile >> hi1 >> hi2; + spline = new LineSeg<D>(geompoints[hi1-1], + geompoints[hi2-1]); + } + else if (strcmp (buf, "3") == 0) + { // a rational spline + infile >> hi1 >> hi2 >> hi3; + spline = new SplineSeg3<D> (geompoints[hi1-1], + geompoints[hi2-1], + geompoints[hi3-1]); + } + else if (strcmp (buf, "4") == 0) + { // an arc + infile >> hi1 >> hi2 >> hi3; + spline = new CircleSeg<D> (geompoints[hi1-1], + geompoints[hi2-1], + geompoints[hi3-1]); + } + else if (strcmp (buf, "discretepoints") == 0) + { + int npts; + infile >> npts; + Array< Point<D> > pts(npts); + for (int j = 0; j < npts; j++) + for(int k=0; k<D; k++) + infile >> pts[j](k); + + spline = new DiscretePointsSeg<D> (pts); + } + else if (strcmp (buf, "bsplinepoints") == 0) + { + int npts,order; + infile >> npts; + infile >> order; + Array< Point<D> > pts(npts); + for (int j = 0; j < npts; j++) + for(int k=0; k<D; k++) + infile >> pts[j](k); + if(order<2) + cerr<<"Minimum order of 2 is required!!"<<endl; + else if(order==2) + spline = new BSplineSeg<D,2> (pts); + else if(order==3) + spline = new BSplineSeg<D,3> (pts); + else if(order==4) + spline = new BSplineSeg<D,4> (pts); + else if(order>4) + cerr<<"Maximum allowed order is 4!!"<<endl; + } + + // 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 ; + } + + // 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<numdomains; i++) + materials [ i ] = new char[100]; + + for ( int i=0; i<numdomains && infile.good(); i++) + { + TestComment ( infile ); + infile >> 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 (double l, double h, double h1, double h2, + double hcurve, double elto0, Array<double> & points) + { + // cout << "calcpart, h = " << h << ", h1 = " << h1 << ", h2 = " << h2 << ", hcurve = " << hcurve << endl; + int i, j, n, nel; + double sum, t, dt, fun, fperel, oldf, f; + + n = 1000; + + points.SetSize (0); + + sum = 0; + dt = l / n; + t = 0.5 * dt; + for (i = 1; i <= n; i++) + { + fun = min3 (hcurve, t/elto0 + h1, (l-t)/elto0 + h2); + sum += dt / fun; + t += dt; + } + + nel = int (sum+1); + fperel = sum / nel; + + points.Append (0); + + i = 1; + oldf = 0; + t = 0.5 * dt; + for (j = 1; j <= n && i < nel; j++) + { + fun = min3 (hcurve, t/elto0 + h1, (l-t)/elto0 + h2); + + f = oldf + dt / fun; + + while (f > i * fperel && i < nel) + { + points.Append ( (l/n) * (j-1 + (i * fperel - oldf) / (f - oldf)) ); + i++; + } + oldf = f; + t += dt; + } + points.Append (l); + } + + + + string SplineGeometry2d :: GetBCName( const int bcnr ) const + { + if ( bcnames.Size() >= bcnr) + if (bcnames[bcnr-1] ) + return *bcnames[bcnr-1]; + return "default"; + } + + string * SplineGeometry2d :: BCNamePtr( const int bcnr ) + { + if ( bcnr > bcnames.Size() ) + return 0; + else + return bcnames[bcnr-1]; + } + + + + + + void SplineGeometry2d :: GetMaterial( const int domnr, char* & material ) + { + if ( materials.Size() >= domnr) + material = materials[domnr-1]; + else + material = 0; + } + + + double SplineGeometry2d :: GetDomainMaxh( const int domnr ) + { + if ( maxh.Size() >= domnr && domnr > 0) + return maxh[domnr-1]; + else + return -1; + } + + + + extern void MeshFromSpline2D (SplineGeometry2d & geometry, + Mesh *& mesh, + MeshingParameters & mp); + + + int SplineGeometry2d :: GenerateMesh (Mesh*& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend) + { + MeshFromSpline2D (*this, mesh, mparam); + return 0; + } + + + Refinement & SplineGeometry2d :: GetRefinement () const + { + return * new Refinement2d (*this); + } + +} diff --git a/contrib/Netgen/libsrc/geom2d/geometry2d.hpp b/contrib/Netgen/libsrc/geom2d/geometry2d.hpp new file mode 100644 index 0000000000..ef0bd015f5 --- /dev/null +++ b/contrib/Netgen/libsrc/geom2d/geometry2d.hpp @@ -0,0 +1,184 @@ +#ifndef FILE_GEOMETRY2D +#define FILE_GEOMETRY2D + +/* *************************************************************************/ +/* File: geometry2d.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Jul. 02 */ +/* *************************************************************************/ + +#include <myadt.hpp> +#include <gprim.hpp> + + +// #include "../gprim/spline.hpp" +// #include "../gprim/splinegeometry.hpp" +#include "geom2dmesh.hpp" + +namespace netgen +{ + + class SplineSegExt : public SplineSeg<2> + { + public: + const 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; + /// perfrom anisotropic refinement (hp-refinement) to edge + bool hpref_left; + /// perfrom anisotropic refinement (hp-refinement) to edge + bool hpref_right; + /// + int layer; + + SplineSegExt (const SplineSeg<2> & hseg) + : seg(hseg) + { + layer = 1; + } + + + 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<Point<2> > & points) const + { + seg.GetPoints (n, points); + } + + virtual double MaxCurvature () const + { + return seg.MaxCurvature(); + } + + virtual string GetType () const + { + return seg.GetType(); + } + + }; + + + + + class SplineGeometry2d : public SplineGeometry<2>, public NetgenGeometry + { + protected: + Array<char*> materials; + Array<double> maxh; + Array<bool> quadmeshing; + Array<bool> tensormeshing; + Array<int> layer; + Array<string*> bcnames; + double elto0; + + + 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 ) ; + + + + const SplineSegExt & GetSpline (const int i) const + { + return dynamic_cast<const SplineSegExt&> (*splines[i]); + } + + SplineSegExt & GetSpline (const int i) + { + return dynamic_cast<SplineSegExt&> (*splines[i]); + } + + + DLL_HEADER virtual int GenerateMesh (Mesh*& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend); + + void PartitionBoundary (double h, Mesh & mesh2d); + + void CopyEdgeMesh (int from, int to, Mesh & mesh2d, Point3dTree & searchtree); + + + void GetMaterial( const int domnr, char* & material ); + + double GetDomainMaxh ( const int domnr ); + 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 ( const int bcnr ) const; + + string * BCNamePtr ( const int bcnr ); + + + DLL_HEADER virtual Refinement & GetRefinement () const; + }; +} + + + + + + + +#endif diff --git a/contrib/Netgen/libsrc/geom2d/spline2d.hpp b/contrib/Netgen/libsrc/geom2d/spline2d.hpp new file mode 100644 index 0000000000..20affa49aa --- /dev/null +++ b/contrib/Netgen/libsrc/geom2d/spline2d.hpp @@ -0,0 +1,234 @@ + + + + +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; + /// perfrom 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<Point<2> > & 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<Point<2> > pts; + GeomPoint2d p1, p2; +public: + /// + DiscretePointsSegment (const Array<Point<2> > & 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 diff --git a/contrib/Netgen/libsrc/geom2d/splinegeometry2.hpp b/contrib/Netgen/libsrc/geom2d/splinegeometry2.hpp new file mode 100644 index 0000000000..6b1428bedb --- /dev/null +++ b/contrib/Netgen/libsrc/geom2d/splinegeometry2.hpp @@ -0,0 +1,103 @@ + + +OLD IMPLEMENTATION, NOT USED ANYMORE! + + + + +#ifndef FILE_SPLINEGEOMETRY2 +#define FILE_SPLINEGEOMETRY2 + +/**************************************************************************/ +/* File: splinegeometry2.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 24. Jul. 96 */ +/**************************************************************************/ + +#include "splinegeometry.hpp" + +#ifdef OLDSPLINEGEOMETRY + + +/// +extern void LoadBoundarySplines (const char * filename, + Array<GeomPoint2d> & geompoints, + Array<SplineSegment*> & splines, + double & elto0); +/// +extern void PartitionBoundary (const Array<SplineSegment*> & splines, + double h, double elto0, + Mesh & mesh2d); + + +class CSGScanner; + +class SplineGeometry2d +{ + Array<GeomPoint2d> geompoints; + Array<SplineSegment*> splines; + double elto0; + + +private: + void AppendSegment(SplineSegment * spline, const int leftdomain, const int rightdomain, + const int bc, + const double reffac, const bool hprefleft, const bool hprefright, + const int copyfrom); + +public: + ~SplineGeometry2d(); + + void Load (const char * filename); + void CSGLoad (CSGScanner & scan); + void PartitionBoundary (double h, Mesh & mesh2d); + + void CopyEdgeMesh (int from, int to, Mesh & mesh2d, Point3dTree & searchtree); + + const Array<SplineSegment*> & GetSplines () const + { return splines; } + + int GetNSplines (void) const { return splines.Size(); } + string GetSplineType (const int i) const { return splines[i]->GetType(); } + SplineSegment & GetSpline (const int i) {return *splines[i];} + const SplineSegment & GetSpline (const int i) const {return *splines[i];} + + void GetBoundingBox (Box<2> & box) const; + + int GetNP () const { return geompoints.Size(); } + const GeomPoint2d & GetPoint(int i) const { return geompoints[i]; } + + void SetGrading (const double grading); + void AppendPoint (const double x, const double y, const double reffac = 1., const bool hpref = false); + + void AppendLineSegment (const int n1, const int n2, + const int leftdomain, const int rightdomain, const int bc = -1, + const double reffac = 1., + const bool hprefleft = false, const bool hprefright = false, + const int copyfrom = -1); + void AppendSplineSegment (const int n1, const int n2, const int n3, + const int leftdomain, const int rightdomain, const int bc = -1, + const double reffac = 1., + const bool hprefleft = false, const bool hprefright = false, + const int copyfrom = -1); + void AppendCircleSegment (const int n1, const int n2, const int n3, + const int leftdomain, const int rightdomain, const int bc = -1, + const double reffac = 1., + const bool hprefleft = false, const bool hprefright = false, + const int copyfrom = -1); + void AppendDiscretePointsSegment (const Array< Point<2> > & points, + const int leftdomain, const int rightdomain, const int bc = -1, + const double reffac = 1., + const bool hprefleft = false, const bool hprefright = false, + const int copyfrom = -1); + +}; + + +void MeshFromSpline2D (SplineGeometry2d & geometry, + Mesh *& mesh, + MeshingParameters & mp); + +#endif + +#endif diff --git a/contrib/Netgen/libsrc/geom2d/vsgeom2d.cpp b/contrib/Netgen/libsrc/geom2d/vsgeom2d.cpp new file mode 100644 index 0000000000..6d1081453a --- /dev/null +++ b/contrib/Netgen/libsrc/geom2d/vsgeom2d.cpp @@ -0,0 +1,110 @@ +#include <meshing.hpp> +#include <geometry2d.hpp> +#include <visual.hpp> + +#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(); + glMultMatrixf (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<Point<2> > points, otherpoints; + + for (int i = 1; i <= geometry2d->GetSplines().Size(); i++) + { + geometry2d->GetSplines().Get(i)->GetPoints (20, 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(); + } +} diff --git a/contrib/Netgen/libsrc/geom2d/vsgeom2d.hpp b/contrib/Netgen/libsrc/geom2d/vsgeom2d.hpp new file mode 100644 index 0000000000..ffb44711e1 --- /dev/null +++ b/contrib/Netgen/libsrc/geom2d/vsgeom2d.hpp @@ -0,0 +1,28 @@ +#ifndef FILE_VSGEOM2D +#define FILE_VSGEOM2D + +/**************************************************************************/ +/* File: vsgeom2d.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 05. Jan. 2011 */ +/**************************************************************************/ + +namespace netgen +{ + + class 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 diff --git a/contrib/Netgen/libsrc/gprim/Makefile.am b/contrib/Netgen/libsrc/gprim/Makefile.am new file mode 100644 index 0000000000..7d60c42d85 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/Makefile.am @@ -0,0 +1,7 @@ +noinst_HEADERS = adtree.hpp geom3d.hpp geomobjects2.hpp geomops2.hpp geomtest3d.hpp transform3d.hpp geom2d.hpp geomfuncs.hpp geomobjects.hpp geomops.hpp gprim.hpp spline.hpp splinegeometry.hpp + +AM_CPPFLAGS = -I$(top_srcdir)/libsrc/include +METASOURCES = AUTO +noinst_LTLIBRARIES = libgprim.la +libgprim_la_SOURCES = adtree.cpp geom2d.cpp geom3d.cpp geomfuncs.cpp \ + geomtest3d.cpp transform3d.cpp spline.cpp splinegeometry.cpp diff --git a/contrib/Netgen/libsrc/gprim/adtree.cpp b/contrib/Netgen/libsrc/gprim/adtree.cpp new file mode 100644 index 0000000000..592a6238c4 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/adtree.cpp @@ -0,0 +1,2165 @@ +#include <mystdlib.h> + + +#include <myadt.hpp> +// class DenseMatrix; +#include <gprim.hpp> + +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 <int> & 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<int> & pis) const + { + static Array<ADTreeNode3*> stack(1000); + static Array<int> 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) + { + 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<int> & pis) const + { + static Array<ADTreeNode3Div*> stack(1000); + static Array<int> 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<int> & pis) const + { + static Array<ADTreeNode3M*> stack(1000); + static Array<int> 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<int> & pis) const + { + static Array<ADTreeNode3F*> 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<int> & pis) const + { + static Array<ADTreeNode3FM*> 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<int> & pis) const + { + static Array<inttn6> stack(10000); + + stack.SetSize (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) + { + 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; + } + + + + + + +#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<int> & pis) const + { + static Array<ADTreeNode6F*> 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<int> & 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); + } + + + + + + + + + + + Box3dTree :: Box3dTree (const Point<3> & apmin, const Point<3> & apmax) + { + boxpmin = apmin; + boxpmax = apmax; + float tpmin[6], tpmax[6]; + for (int i = 0; i < 3; i++) + { + tpmin[i] = tpmin[i+3] = boxpmin(i); + tpmax[i] = tpmax[i+3] = boxpmax(i); + } + tree = new ADTree6 (tpmin, tpmax); + } + + Box3dTree :: ~Box3dTree () + { + delete tree; + } + + void Box3dTree :: Insert (const Point<3> & bmin, const Point<3> & bmax, int pi) + { + float tp[6]; + + for (int i = 0; i < 3; i++) + { + tp[i] = bmin(i); + tp[i+3] = bmax(i); + } + + tree->Insert (tp, pi); + } + + void Box3dTree ::GetIntersecting (const Point<3> & pmin, const Point<3> & pmax, + Array<int> & pis) const + { + float tpmin[6]; + float tpmax[6]; + + for (int i = 0; i < 3; i++) + { + tpmin[i] = boxpmin(i); + tpmax[i] = pmax(i); + + tpmin[i+3] = pmin(i); + tpmax[i+3] = boxpmax(i); + } + + tree->GetIntersecting (tpmin, tpmax, pis); + } + +} diff --git a/contrib/Netgen/libsrc/gprim/adtree.hpp b/contrib/Netgen/libsrc/gprim/adtree.hpp new file mode 100644 index 0000000000..d0f02b6dee --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/adtree.hpp @@ -0,0 +1,486 @@ +#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<ADTreeNode*> ela; + const ADTreeCriterion * criterion; + + Array<ADTreeNode*> stack; + Array<int> 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<int> & pis) const; + void SetCriterion (ADTreeCriterion & acriterion); + void Reset (); + int Next (); + void GetMatch (Array<int> & 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<ADTreeNode3*> 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<int> & 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<ADTreeNode3Div*> 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<int> & 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<ADTreeNode3M*> 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<int> & 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<ADTreeNode3F*> 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<int> & 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<ADTreeNode3FM*> 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<int> & 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<ADTreeNode6*> 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<int> & 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; +}; + + + + +/* + +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<ADTreeNode6F*> 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<int> & 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<int> & pis) const; + const ADTree3 & Tree() const { return *tree; }; +}; + + + +class Box3dTree +{ + ADTree6 * tree; + Point<3> boxpmin, boxpmax; +public: + Box3dTree (const Point<3> & apmin, const Point<3> & apmax); + ~Box3dTree (); + void Insert (const Point<3> & bmin, const Point<3> & bmax, int pi); + void Insert (const Box<3> & box, int pi) + { + Insert (box.PMin(), box.PMax(), pi); + } + void DeleteElement (int pi) + { tree->DeleteElement(pi); } + void GetIntersecting (const Point<3> & pmin, const Point<3> & pmax, + Array<int> & pis) const; + + const ADTree6 & Tree() const { return *tree; }; +}; + +} + +#endif diff --git a/contrib/Netgen/libsrc/gprim/geom2d.cpp b/contrib/Netgen/libsrc/gprim/geom2d.cpp new file mode 100644 index 0000000000..34263348cc --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geom2d.cpp @@ -0,0 +1,489 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <gprim.hpp> + +#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<d2) d2 = d1; + if (d3<d4) d4 = d3; + dd = ( d2 < d4 ) ? d2 : d4; + } + return dd; +} + + +Point2d CrossPoint (const Line2d & l1, const Line2d & l2) + { + double den = Cross (l1.Delta(), l2.Delta()); + double num = Cross ( (l2.P1() - l1.P1()), l2.Delta()); + + if (den == 0) + return l1.P1(); + else + return l1.P1() + (num/den) * l1.Delta(); +} + + +int CrossPointBarycentric (const Line2d & l1, const Line2d & l2, + double & lam1, double & lam2) +{ + // p = l1.1 + lam1 (l1.2-l1.1) = l2.1 + lam2 (l2.2-l2.1) + double a11 = l1.p2.X() - l1.p1.X(); + double a21 = l1.p2.Y() - l1.p1.Y(); + double a12 = -(l2.p2.X() - l2.p1.X()); + double a22 = -(l2.p2.Y() - l2.p1.Y()); + + double b1 = l2.p1.X() - l1.p1.X(); + double b2 = l2.p1.Y() - l1.p1.Y(); + + double det = a11*a22 - a12 * a21; + if (det == 0) + return 1; + + lam1 = (a22 * b1 - a12 * b2) / det; + lam2 = (a11 * b2 - a21 * b1) / det; + return 0; +} + + + + +int Parallel (const Line2d & l1, const Line2d & l2, double peps) + { + double p = fabs (Cross (l1.Delta(), l2.Delta())); + // (*mycout) << endl << p << " " << l1.Length() << " " << l2.Length() << endl; + return p <= peps * l1.Length() * l2.Length(); +} + +int IsOnLine (const Line2d & 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; +} + +#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); + } + + +} diff --git a/contrib/Netgen/libsrc/gprim/geom2d.hpp b/contrib/Netgen/libsrc/gprim/geom2d.hpp new file mode 100644 index 0000000000..334df09ca5 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geom2d.hpp @@ -0,0 +1,886 @@ +#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<Point2d> 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 diff --git a/contrib/Netgen/libsrc/gprim/geom3d.cpp b/contrib/Netgen/libsrc/gprim/geom3d.cpp new file mode 100644 index 0000000000..04ecd13764 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geom3d.cpp @@ -0,0 +1,731 @@ +#include <algorithm> +#include <mystdlib.h> + +#include <myadt.hpp> +#include <gprim.hpp> + +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()); +} + + +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; + */ +} + + +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<Point3d> & p, + Array<Point3d> & 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(); +} + + +} diff --git a/contrib/Netgen/libsrc/gprim/geom3d.hpp b/contrib/Netgen/libsrc/gprim/geom3d.hpp new file mode 100644 index 0000000000..05216d8f0f --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geom3d.hpp @@ -0,0 +1,746 @@ +#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<Point3d> & p, Array<Point3d> & pp) const; + /// + void FromPlain (const Point3d & pp, Point3d & p) const; + }; + +} + + +#endif diff --git a/contrib/Netgen/libsrc/gprim/geomfuncs.cpp b/contrib/Netgen/libsrc/gprim/geomfuncs.cpp new file mode 100644 index 0000000000..b2ac83824a --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomfuncs.cpp @@ -0,0 +1,111 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <gprim.hpp> + +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; + + + +} + + +} diff --git a/contrib/Netgen/libsrc/gprim/geomfuncs.hpp b/contrib/Netgen/libsrc/gprim/geomfuncs.hpp new file mode 100644 index 0000000000..66cbca81ef --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomfuncs.hpp @@ -0,0 +1,170 @@ +#ifndef FILE_GEOMFUNCS +#define FILE_GEOMFUNCS + +/* *************************************************************************/ +/* File: geomfuncs.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Jul. 02 */ +/* *************************************************************************/ + + +namespace netgen +{ + + template <int D> + inline double Abs (const Vec<D> & v) + { + double sum = 0; + for (int i = 0; i < D; i++) + sum += v(i) * v(i); + return sqrt (sum); + } + + + template <int D> + inline double Abs2 (const Vec<D> & v) + { + double sum = 0; + for (int i = 0; i < D; i++) + sum += v(i) * v(i); + return sum; + } + + + + template <int D> + inline double Dist (const Point<D> & a, const Point<D> & b) + { + return Abs (a-b); + } + + template <int D> + inline double Dist2 (const Point<D> & a, const Point<D> & b) + { + return Abs2 (a-b); + } + + + template <int D> + inline Point<D> Center (const Point<D> & a, const Point<D> & b) + { + Point<D> res; + for (int i = 0; i < D; i++) + res(i) = 0.5 * (a(i) + b(i)); + return res; + } + + template <int D> + inline Point<D> Center (const Point<D> & a, const Point<D> & b, const Point<D> & c) + { + Point<D> res; + for (int i = 0; i < D; i++) + res(i) = (1.0/3.0) * (a(i) + b(i) + c(i)); + return res; + } + + template <int D> + inline Point<D> Center (const Point<D> & a, const Point<D> & b, const Point<D> & c, const Point<D> & d) + { + Point<D> 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) + + inline Vec<3> Cross (Vec<3> v1, Vec<3> v2) + { + return Vec<3> + ( 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 <int H, int W> + 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 diff --git a/contrib/Netgen/libsrc/gprim/geomobjects.hpp b/contrib/Netgen/libsrc/gprim/geomobjects.hpp new file mode 100644 index 0000000000..29b9bb1b53 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomobjects.hpp @@ -0,0 +1,370 @@ +#ifndef FILE_OBJECTS +#define FILE_OBJECTS + +/* *************************************************************************/ +/* File: geomobjects.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Jul. 02 */ +/* *************************************************************************/ + + +namespace netgen +{ + + + template <int D> class Vec; + template <int D> class Point; + + + template <int D> + class Point + { + + protected: + double x[D]; + + public: + Point () { ; } + Point (double ax) { for (int i = 0; i < D; i++) x[i] = 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<D> & p2) + { for (int i = 0; i < D; i++) x[i] = p2.x[i]; } + + explicit Point (const Vec<D> & v) + { for (int i = 0; i < D; i++) x[i] = v(i); } + + + Point & operator= (const Point<D> & p2) + { + for (int i = 0; i < D; i++) x[i] = p2.x[i]; + return *this; + } + + Point & operator= (double val) + { + for (int i = 0; i < D; i++) x[i] = val; + 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 <int D> + class Vec + { + + protected: + double x[D]; + + public: + Vec () { ; } // for (int i = 0; i < D; i++) x[i] = 0; } + 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<D> & p2) + { for (int i = 0; i < D; i++) x[i] = p2.x[i]; } + + explicit Vec (const Point<D> & p) + { for (int i = 0; i < D; i++) x[i] = p(i); } + + Vec (const Vec<D> & p1, const Vec<D> & p2) + { for(int i=0; i<D; i++) x[i] = p2(i)-p1(1); } + + + + Vec & operator= (const Vec<D> & p2) + { + for (int i = 0; i < D; i++) x[i] = p2.x[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<D> & Normalize () + { + double l = Length(); + if (l != 0) + for (int i = 0; i < D; i++) + x[i] /= l; + return *this; + } + + Vec<D> GetNormal () const; + }; + + + + + + template <int H, int W=H> + 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]; } + double & operator() (int i) { return x[i]; } + const double & operator() (int i) const { return x[i]; } + + Vec<H> Col (int i) const + { + Vec<H> hv; + for (int j = 0; j < H; j++) + hv(j) = x[j*W+i]; + return hv; + } + + Vec<W> Row (int i) const + { + Vec<W> hv; + for (int j = 0; j < W; j++) + hv(j) = x[i*W+j]; + return hv; + } + + void Solve (const Vec<H> & rhs, Vec<W> & sol) const + { + Mat<W,H> inv; + CalcInverse (*this, inv); + sol = inv * rhs; + } + }; + + + + + template <int D> + class Box + { + protected: + Point<D> pmin, pmax; + public: + Box () { ; } + + Box ( const Point<D> & p1) + { + for (int i = 0; i < D; i++) + pmin(i) = pmax(i) = p1(i); + } + + + Box ( const Point<D> & p1, const Point<D> & p2) + { + for (int i = 0; i < D; i++) + { + pmin(i) = min2(p1(i), p2(i)); + pmax(i) = max2(p1(i), p2(i)); + } + } + + enum EB_TYPE { EMPTY_BOX = 1 }; + Box ( EB_TYPE et ) + { + pmin = Point<3> (1e99, 1e99, 1e99); + pmax = Point<3> (-1e99, -1e99, -1e99); + } + + const Point<D> & PMin () const { return pmin; } + const Point<D> & PMax () const { return pmax; } + + void Set (const Point<D> & p) + { pmin = pmax = p; } + + void Add (const Point<D> & 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<D> Center () const + { + Point<D> 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<D> GetPointNr (int nr) const + { + Point<D> p; + for (int i = 0; i < D; i++) + { + p(i) = (nr & 1) ? pmax(i) : pmin(i); + nr >>= 1; + } + return p; + } + + + bool Intersect (const Box<D> & 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<D> & 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 <int D> + class BoxSphere : public Box<D> + { + protected: + /// + Point<D> c; + /// + double diam; + /// + double inner; + public: + /// + BoxSphere () { }; + /// + BoxSphere (const Box<D> & box) + : Box<D> (box) + { + CalcDiamCenter(); + }; + + /// + BoxSphere ( Point<D> apmin, Point<D> apmax ) + : Box<D> (apmin, apmax) + { + CalcDiamCenter(); + } + + /// + const Point<D> & 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<D>::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 diff --git a/contrib/Netgen/libsrc/gprim/geomobjects2.hpp b/contrib/Netgen/libsrc/gprim/geomobjects2.hpp new file mode 100644 index 0000000000..014a38525a --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomobjects2.hpp @@ -0,0 +1,366 @@ +#ifndef FILE_OBJECTS +#define FILE_OBJECTS + +/* *************************************************************************/ +/* File: geomobjects.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Jul. 02 */ +/* *************************************************************************/ + +template <typename T> +class VecExpr +{ +public: + VecExpr () { ; } + double operator() (int i) const { return static_cast<const T&> (*this) (i); } +}; + + +template <int D> class Vec; +template <int D> class Point; + + +template <int D> +class Point : public VecExpr<Point<D> > +{ + +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<D> & p2) + { for (int i = 0; i < D; i++) x[i] = p2.x[i]; } + + explicit Point (const Vec<D> & v) + { for (int i = 0; i < D; i++) x[i] = v(i); } + + + template <typename T> + explicit Point (const VecExpr<T> & expr) + { + for (int i = 0; i < D; i++) x[i] = expr(i); + } + + Point & operator= (const Point<D> & p2) + { + for (int i = 0; i < D; i++) x[i] = p2.x[i]; + return *this; + } + + template <typename T> + Point & operator= (const VecExpr<T> & 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 <int D> +class Vec : public VecExpr<Vec<D> > +{ + +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<D> & p2) + { for (int i = 0; i < D; i++) x[i] = p2.x[i]; } + + explicit Vec (const Point<D> & p) + { for (int i = 0; i < D; i++) x[i] = p(i); } + + template <typename T> + explicit Vec (const VecExpr<T> & expr) + { + for (int i = 0; i < D; i++) x[i] = expr(i); + } + + + Vec & operator= (const Vec<D> & p2) + { + for (int i = 0; i < D; i++) x[i] = p2.x[i]; + return *this; + } + + template <typename T> + Vec & operator= (const VecExpr<T> & 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<D> & Normalize () + { + double l = Length(); + if (l != 0) + for (int i = 0; i < D; i++) + x[i] /= l; + return *this; + } + + Vec<D> GetNormal () const; +}; + + + + + +template <int H, int W=H> +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<H> Col (int i) const + { + Vec<H> hv; + for (int j = 0; j < H; j++) + hv(j) = x[j*W+i]; + return hv; + } + + Vec<W> Row (int i) const + { + Vec<W> hv; + for (int j = 0; j < W; j++) + hv(j) = x[i*W+j]; + return hv; + } + + void Solve (const Vec<H> & rhs, Vec<W> & sol) const + { + Mat<W,H> inv; + CalcInverse (*this, inv); + sol = inv * rhs; + } +}; + + + + +template <int D> +class Box +{ +protected: + Point<D> pmin, pmax; +public: + Box () { ; } + Box ( const Point<D> & p1, const Point<D> & p2) + { + for (int i = 0; i < D; i++) + { + pmin(i) = min2(p1(i), p2(i)); + pmax(i) = max2(p1(i), p2(i)); + } + } + + const Point<D> & PMin () const { return pmin; } + const Point<D> & PMax () const { return pmax; } + + void Set (const Point<D> & p) + { pmin = pmax = p; } + + void Add (const Point<D> & 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<D> Center () const + { + Point<D> 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<D> GetPointNr (int nr) const + { + Point<D> p; + for (int i = 0; i < D; i++) + { + p(i) = (nr & 1) ? pmax(i) : pmin(i); + nr >>= 1; + } + return p; + } + + + bool Intersect (const Box<D> & 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<D> & 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 <int D> +class BoxSphere : public Box<D> +{ +protected: + /// + Point<D> c; + /// + double diam; + /// + double inner; +public: + /// + BoxSphere () { }; + /// + BoxSphere ( Point<D> pmin, Point<D> pmax ) + : Box<D> (pmin, pmax) + { + CalcDiamCenter(); + } + + /// + const Point<D> & 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<D>::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 diff --git a/contrib/Netgen/libsrc/gprim/geomops.hpp b/contrib/Netgen/libsrc/gprim/geomops.hpp new file mode 100644 index 0000000000..90c3cb6bf5 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomops.hpp @@ -0,0 +1,394 @@ +#ifndef FILE_GEOMOPS +#define FILE_GEOMOPS + +/* *************************************************************************/ +/* File: geomops.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Jul. 02 */ +/* *************************************************************************/ + + +namespace netgen +{ + + /* + + Point - Vector operations + + */ + + + template <int D> + inline Vec<D> operator+ (const Vec<D> & a, const Vec<D> & b) + { + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) + b(i); + return res; + } + + + + template <int D> + inline Point<D> operator+ (const Point<D> & a, const Vec<D> & b) + { + Point<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) + b(i); + return res; + } + + + + template <int D> + inline Vec<D> operator- (const Point<D> & a, const Point<D> & b) + { + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) - b(i); + return res; + } + + template <int D> + inline Point<D> operator- (const Point<D> & a, const Vec<D> & b) + { + Point<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) - b(i); + return res; + } + + template <int D> + inline Vec<D> operator- (const Vec<D> & a, const Vec<D> & b) + { + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) - b(i); + return res; + } + + + + template <int D> + inline Vec<D> operator* (double s, const Vec<D> & b) + { + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = s * b(i); + return res; + } + + + template <int D> + inline double operator* (const Vec<D> & a, const Vec<D> & b) + { + double sum = 0; + for (int i = 0; i < D; i++) + sum += a(i) * b(i); + return sum; + } + + + + template <int D> + inline Vec<D> operator- (const Vec<D> & b) + { + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = -b(i); + return res; + } + + + template <int D> + inline Point<D> & operator+= (Point<D> & a, const Vec<D> & b) + { + for (int i = 0; i < D; i++) + a(i) += b(i); + return a; + } + + template <int D> + inline Vec<D> & operator+= (Vec<D> & a, const Vec<D> & b) + { + for (int i = 0; i < D; i++) + a(i) += b(i); + return a; + } + + + template <int D> + inline Point<D> & operator-= (Point<D> & a, const Vec<D> & b) + { + for (int i = 0; i < D; i++) + a(i) -= b(i); + return a; + } + + template <int D> + inline Vec<D> & operator-= (Vec<D> & a, const Vec<D> & b) + { + for (int i = 0; i < D; i++) + a(i) -= b(i); + return a; + } + + + + template <int D> + inline Vec<D> & operator*= (Vec<D> & a, double s) + { + for (int i = 0; i < D; i++) + a(i) *= s; + return a; + } + + + template <int D> + inline Vec<D> & operator/= (Vec<D> & a, double s) + { + for (int i = 0; i < D; i++) + a(i) /= s; + return a; + } + + + + + // Matrix - Vector operations + + /* + template <int H, int W> + inline Vec<H> operator* (const Mat<H,W> & m, const Vec<W> & v) + { + Vec<H> 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 <int H1, int W1, int H2, int W2> + inline Mat<H1,W2> operator* (const Mat<H1,W1> & a, const Mat<H2,W2> & b) + { + Mat<H1,W2> 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<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; + } + + + 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 <int H, int W> + inline Mat<W,H> Trans (const Mat<H,W> & m) + { + Mat<W,H> res; + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) + res(j,i) = m(i,j); + return res; + } + + + + + + + + + + + + template <int D> + inline ostream & operator<< (ostream & ost, const Vec<D> & a) + { + ost << "("; + for (int i = 0; i < D-1; i++) + ost << a(i) << ", "; + ost << a(D-1) << ")"; + return ost; + } + + template <int D> + inline ostream & operator<< (ostream & ost, const Point<D> & a) + { + ost << "("; + for (int i = 0; i < D-1; i++) + ost << a(i) << ", "; + ost << a(D-1) << ")"; + return ost; + } + + template <int D> + inline ostream & operator<< (ostream & ost, const Box<D> & b) + { + ost << b.PMin() << " - " << b.PMax(); + return ost; + } + + template <int H, int W> + inline ostream & operator<< (ostream & ost, const Mat<H,W> & 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 diff --git a/contrib/Netgen/libsrc/gprim/geomops2.hpp b/contrib/Netgen/libsrc/gprim/geomops2.hpp new file mode 100644 index 0000000000..c615da14ec --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomops2.hpp @@ -0,0 +1,428 @@ +#ifndef FILE_GEOMOPS +#define FILE_GEOMOPS + +/* *************************************************************************/ +/* File: geomops.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Jul. 02 */ +/* *************************************************************************/ + + +/* + +Point - Vector operations + + */ + + + + +template <class TA, class TB> +class SumExpr : public VecExpr<SumExpr<TA, TB> > +{ + 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 <typename TA, typename TB> +inline SumExpr<TA,TB> +operator+ (const VecExpr<TA> & a, const VecExpr<TB> & b) +{ + return SumExpr<TA,TB> (static_cast <const TA&> (a), static_cast <const TB&> (b)); +} + +/* +template <int D1, int D2> +inline SumExpr<const Vec<D1>&, const Vec<D2>&> +operator+ (const Vec<D1> & a, const Vec<D2> & b) +{ + return SumExpr<const Vec<D1>&, const Vec<D2>&> (a, b); +} +*/ + + + + + +/* +template <int D> +inline Vec<D> operator+ (const Vec<D> & a, const Vec<D> & b) +{ + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) + b(i); + return res; +} +*/ + +template <int D> +inline Point<D> operator+ (const Point<D> & a, const Vec<D> & b) +{ + Point<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) + b(i); + return res; +} + + +template <int D> +inline Vec<D> operator- (const Point<D> & a, const Point<D> & b) +{ + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) - b(i); + return res; +} + +template <int D> +inline Point<D> operator- (const Point<D> & a, const Vec<D> & b) +{ + Point<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) - b(i); + return res; +} + +template <int D> +inline Vec<D> operator- (const Vec<D> & a, const Vec<D> & b) +{ + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) - b(i); + return res; +} + + +template <int D> +inline Vec<D> operator* (double s, const Vec<D> & b) +{ + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = s * b(i); + return res; +} + + +template <int D> +inline double operator* (const Vec<D> & a, const Vec<D> & b) +{ + double sum = 0; + for (int i = 0; i < D; i++) + sum += a(i) * b(i); + return sum; +} + + + +template <int D> +inline Vec<D> operator- (const Vec<D> & b) +{ + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = -b(i); + return res; +} + + +template <int D> +inline Point<D> & operator+= (Point<D> & a, const Vec<D> & b) +{ + for (int i = 0; i < D; i++) + a(i) += b(i); + return a; +} + + +template <int D, typename T> +inline Point<D> & operator+= (Point<D> & a, const VecExpr<T> & b) +{ + for (int i = 0; i < D; i++) + a(i) += b(i); + return a; +} + +template <int D> +inline Vec<D> & operator+= (Vec<D> & a, const Vec<D> & b) +{ + for (int i = 0; i < D; i++) + a(i) += b(i); + return a; +} + + + + + +template <int D> +inline Point<D> & operator-= (Point<D> & a, const Vec<D> & b) +{ + for (int i = 0; i < D; i++) + a(i) -= b(i); + return a; +} + +template <int D, typename T> +inline Point<D> & operator-= (Point<D> & a, const VecExpr<T> & b) +{ + for (int i = 0; i < D; i++) + a(i) -= b(i); + return a; +} + + + + + +template <int D> +inline Vec<D> & operator-= (Vec<D> & a, const Vec<D> & b) +{ + for (int i = 0; i < D; i++) + a(i) -= b(i); + return a; +} + + + +template <int D> +inline Vec<D> & operator*= (Vec<D> & a, double s) +{ + for (int i = 0; i < D; i++) + a(i) *= s; + return a; +} + + +template <int D> +inline Vec<D> & operator/= (Vec<D> & a, double s) +{ + for (int i = 0; i < D; i++) + a(i) /= s; + return a; +} + + + + +// Matrix - Vector operations + +/* +template <int H, int W> +inline Vec<H> operator* (const Mat<H,W> & m, const Vec<W> & v) +{ + Vec<H> 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 <int H1, int W1, int H2, int W2> +inline Mat<H1,W2> operator* (const Mat<H1,W1> & a, const Mat<H2,W2> & b) +{ + Mat<H1,W2> 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 <int H, int W> +inline Mat<W,H> Trans (const Mat<H,W> & m) +{ + Mat<W,H> res; + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) + res(j,i) = m(i,j); + return res; +} + + + + + + + + + + + +template <int D> +inline ostream & operator<< (ostream & ost, const Vec<D> & a) +{ + ost << "("; + for (int i = 0; i < D-1; i++) + ost << a(i) << ", "; + ost << a(D-1) << ")"; + return ost; +} + +template <int D> +inline ostream & operator<< (ostream & ost, const Point<D> & a) +{ + ost << "("; + for (int i = 0; i < D-1; i++) + ost << a(i) << ", "; + ost << a(D-1) << ")"; + return ost; +} + +template <int D> +inline ostream & operator<< (ostream & ost, const Box<D> & b) +{ + ost << b.PMin() << " - " << b.PMax(); + return ost; +} + +template <int H, int W> +inline ostream & operator<< (ostream & ost, const Mat<H,W> & 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 diff --git a/contrib/Netgen/libsrc/gprim/geomtest3d.cpp b/contrib/Netgen/libsrc/gprim/geomtest3d.cpp new file mode 100644 index 0000000000..bb4000b36d --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomtest3d.cpp @@ -0,0 +1,1150 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <gprim.hpp> + +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); + 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 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); + + // (*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.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 + } + + + 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; +} + +} + + diff --git a/contrib/Netgen/libsrc/gprim/geomtest3d.hpp b/contrib/Netgen/libsrc/gprim/geomtest3d.hpp new file mode 100644 index 0000000000..05387da00f --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomtest3d.hpp @@ -0,0 +1,87 @@ +#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); + +/// 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 diff --git a/contrib/Netgen/libsrc/gprim/gprim.hpp b/contrib/Netgen/libsrc/gprim/gprim.hpp new file mode 100644 index 0000000000..016b1280aa --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/gprim.hpp @@ -0,0 +1,33 @@ +#ifndef FILE_GPRIM +#define FILE_GPRIM + +/* *************************************************************************/ +/* File: gprim.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 14. Aug. 97 */ +/* *************************************************************************/ + + +#include <myadt.hpp> +#include <linalg.hpp> + + + + +#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 diff --git a/contrib/Netgen/libsrc/gprim/spline.cpp b/contrib/Netgen/libsrc/gprim/spline.cpp new file mode 100644 index 0000000000..b6789913e4 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/spline.cpp @@ -0,0 +1,497 @@ +/* + +Spline curve for Mesh generator + +*/ + +#include <mystdlib.h> +#include <linalg.hpp> +#include <gprim.hpp> +#include "spline.hpp" + +namespace netgen +{ + + // just for testing (JS) + template <int D> + void ProjectTrivial (const SplineSeg3<D> & seg, + const Point<D> point, Point<D> & point_on_curve, double & t) + { + double mindist = -1; + for (int i = 0; i <= 1000; i++) + { + double ht = double(i)/1000; + Point<D> 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<double> 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<t.Size(); i++) + { + Point<2> 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<int D> + SplineSeg3<D> :: SplineSeg3 (const GeomPoint<D> & ap1, + const GeomPoint<D> & ap2, + const GeomPoint<D> & 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<int D> + inline Point<D> SplineSeg3<D> :: GetPoint (double t) const + { + double x, y, w; + double b1, b2, b3; + + b1 = (1-t)*(1-t); + b2 = weight * t * (1-t); + b3 = t * t; + + 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<D> (x/w, y/w, z/w); + } + else + return Point<D> (x/w, y/w); + } + + + + + template<int D> + Vec<D> SplineSeg3<D> :: 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<D> retval; + for(int i=0; i<D; i++) + retval(i) = b1*p1(i) + b2*p2(i) + b3*p3(i); + + return retval; + + } + + + template<int D> + void SplineSeg3<D> :: 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<D> 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<D> p0 = GetPoint(0); + Vec<D> 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<int D> + void SplineSeg3<D> :: Project (const Point<D> point, Point<D> & 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; + + Point<D> phi; + Vec<D> 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<D>::GetPoint(t); + + double dist = Dist(point,point_on_curve); + + phi = SplineSeg3<D> ::GetPoint(0); + double auxdist = Dist(phi,point); + if(auxdist < dist) + { + t = 0.; + point_on_curve = phi; + dist = auxdist; + } + phi = SplineSeg3<D> ::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<D> ::GetPoint(t0); d0 = Dist(phi,point); + phi = SplineSeg3<D> ::GetPoint(t1); d1 = Dist(phi,point); + phi = SplineSeg3<D> ::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<D> ::GetPoint(t0); d0 = Dist(phi,point); + phi = SplineSeg3<D> ::GetPoint(t1); d1 = Dist(phi,point); + phi = SplineSeg3<D> ::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<D> ::GetPoint(t); + } + //(*testout) << " latest_t " << proj_latest_t << " t " << t << endl; + + proj_latest_t = t; + + /* + // test it by trivial sampling + double ht; + Point<D> 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<int D> + void SplineSeg3<D> :: GetDerivatives (const double t, + Point<D> & point, + Vec<D> & first, + Vec<D> & second) const + { + Vec<D> 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<D; i++) + point(i) = b1*p1(i) + b2*p2(i) + b3*p3(i); + + + first = (b1p - b1*fac1) * v1 + + (b2p - b2*fac1) * v2 + + (b3p - b3*fac1) * v3; + + second = (b1pp/w - 2*b1p*fac1 - b1*fac2) * v1 + + (b2pp/w - 2*b2p*fac1 - b2*fac2) * v2 + + (b3pp/w - 2*b3p*fac1 - b3*fac2) * v3; + } + + + + template<> + 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<int D> + void SplineSeg3<D> :: LineIntersections (const double a, const double b, const double c, + Array < Point<D> > & 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<D> :: GetRawData (Array<double> & data) const + { + data.Append(3); + for(int i=0; i<D; i++) + data.Append(p1[i]); + for(int i=0; i<D; i++) + data.Append(p2[i]); + for(int i=0; i<D; i++) + data.Append(p3[i]); + } + + + + template class SplineSeg3<2>; + template class SplineSeg3<3>; + + + + + + + + +} diff --git a/contrib/Netgen/libsrc/gprim/spline.hpp b/contrib/Netgen/libsrc/gprim/spline.hpp new file mode 100644 index 0000000000..f2701c3e1a --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/spline.hpp @@ -0,0 +1,647 @@ +#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<D> + { + public: + /// refinement factor at point + double refatpoint; + /// max mesh-size at point + double hmax; + /// hp-refinement + bool hpref; + + /// + GeomPoint () { ; } + + /// + GeomPoint (const Point<D> & ap, double aref = 1, bool ahpref=false) + : Point<D>(ap), refatpoint(aref), hmax(1e99), hpref(ahpref) { ; } + }; + + + + + /// base class for 2d - segment + template < int D > + class SplineSeg + { + public: + SplineSeg () { ; } + /// calculates length of curve + virtual double Length () const; + /// returns point at curve, 0 <= t <= 1 + virtual Point<D> GetPoint (double t) const = 0; + /// returns a (not necessarily unit-length) tangent vector for 0 <= t <= 1 + virtual Vec<D> GetTangent (const double t) const + { cerr << "GetTangent not implemented for spline base-class" << endl; Vec<D> dummy; return dummy;} + virtual void GetDerivatives (const double t, + Point<D> & point, + Vec<D> & first, + Vec<D> & second) const {;} + + + /// returns initial point on curve + virtual const GeomPoint<D> & StartPI () const = 0; + /// returns terminal point on curve + virtual const GeomPoint<D> & 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<Point<D> > & 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<D> > & points, const double eps) const + {points.SetSize(0);} + + virtual double MaxCurvature(void) const = 0; + + virtual string GetType(void) const {return "splinebase";} + + virtual void Project (const Point<D> point, Point<D> & point_on_curve, double & t) const + { cerr << "Project not implemented for spline base-class" << endl;} + + virtual void GetRawData (Array<double> & data) const + { cerr << "GetRawData not implemented for spline base-class" << endl;} + + }; + + + /// Straight line form p1 to p2 + template< int D > + class LineSeg : public SplineSeg<D> + { + /// + GeomPoint<D> p1, p2; + public: + /// + LineSeg (const GeomPoint<D> & ap1, const GeomPoint<D> & ap2); + /// + virtual double Length () const; + /// + inline virtual Point<D> GetPoint (double t) const; + /// + virtual Vec<D> GetTangent (const double t) const; + + + virtual void GetDerivatives (const double t, + Point<D> & point, + Vec<D> & first, + Vec<D> & second) const; + /// + virtual const GeomPoint<D> & StartPI () const { return p1; }; + /// + virtual const GeomPoint<D> & EndPI () const { return p2; } + /// + 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<D> > & points, const double eps) const; + + virtual double MaxCurvature(void) const {return 0;} + + virtual void Project (const Point<D> point, Point<D> & point_on_curve, double & t) const; + + virtual void GetRawData (Array<double> & data) const; + }; + + + /// curve given by a rational, quadratic spline (including ellipses) + template< int D > + class SplineSeg3 : public SplineSeg<D> + { + /// + GeomPoint<D> p1, p2, p3; + double weight; + mutable double proj_latest_t; + public: + /// + SplineSeg3 (const GeomPoint<D> & ap1, + const GeomPoint<D> & ap2, + const GeomPoint<D> & ap3); + /// + inline virtual Point<D> GetPoint (double t) const; + /// + virtual Vec<D> GetTangent (const double t) const; + + + DLL_HEADER virtual void GetDerivatives (const double t, + Point<D> & point, + Vec<D> & first, + Vec<D> & second) const; + /// + virtual const GeomPoint<D> & StartPI () const { return p1; }; + /// + virtual const GeomPoint<D> & EndPI () const { return p3; } + /// + virtual void GetCoeff (Vector & coeffs) const; + + virtual string GetType(void) const {return "spline3";} + + const GeomPoint<D> & TangentPoint (void) const { return p2; } + + DLL_HEADER virtual void LineIntersections (const double a, const double b, const double c, + Array < Point<D> > & points, const double eps) const; + + DLL_HEADER virtual double MaxCurvature(void) const; + + DLL_HEADER virtual void Project (const Point<D> point, Point<D> & point_on_curve, double & t) const; + + DLL_HEADER virtual void GetRawData (Array<double> & data) const; + }; + + + // Gundolf Haase 8/26/97 + /// A circle + template < int D > + class CircleSeg : public SplineSeg<D> + { + /// + private: + GeomPoint<D> p1, p2, p3; + //const GeomPoint<D> &p1, &p2, &p3; + Point<D> pm; + double radius, w1,w3; + public: + /// + CircleSeg (const GeomPoint<D> & ap1, + const GeomPoint<D> & ap2, + const GeomPoint<D> & ap3); + /// + virtual Point<D> GetPoint (double t) const; + /// + virtual const GeomPoint<D> & StartPI () const { return p1; } + /// + virtual const GeomPoint<D> & 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<D> & 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<D> > & points, const double eps) const; + + virtual double MaxCurvature(void) const {return 1./radius;} + }; + + + + + + + /// + template<int D> + class DiscretePointsSeg : public SplineSeg<D> + { + Array<Point<D> > pts; + GeomPoint<D> p1n, p2n; + public: + /// + DiscretePointsSeg (const Array<Point<D> > & apts); + /// + virtual ~DiscretePointsSeg (); + /// + virtual Point<D> GetPoint (double t) const; + /// + virtual const GeomPoint<D> & StartPI () const { return p1n; }; + /// + virtual const GeomPoint<D> & EndPI () const { return p2n; } + /// + virtual void GetCoeff (Vector & coeffs) const {;} + + virtual double MaxCurvature(void) const {return 1;} + }; + + + + + + + // calculates length of spline-curve + template<int D> + double SplineSeg<D> :: Length () const + { + int n = 100; + double dt = 1.0 / n; + + Point<D> pold = GetPoint (0); + + double l = 0; + for (int i = 1; i <= n; i++) + { + Point<D> p = GetPoint (i * dt); + l += Dist (p, pold); + pold = p; + } + + return l; + } + + + template<int D> + void SplineSeg<D> :: GetPoints (int n, Array<Point<D> > & points) const + { + points.SetSize (n); + if (n >= 2) + for (int i = 0; i < n; i++) + points[i] = GetPoint(double(i) / (n-1)); + } + + + template<int D> + void SplineSeg<D> :: 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<int D> + LineSeg<D> :: LineSeg (const GeomPoint<D> & ap1, + const GeomPoint<D> & ap2) + : p1(ap1), p2(ap2) + { + ; + } + + + template<int D> + inline Point<D> LineSeg<D> :: GetPoint (double t) const + { + return p1 + t * (p2 - p1); + } + + template<int D> + Vec<D> LineSeg<D> :: GetTangent (const double t) const + { + return p2-p1; + } + + template<int D> + void LineSeg<D> :: GetDerivatives (const double t, + Point<D> & point, + Vec<D> & first, + Vec<D> & second) const + { + first = p2 - p1; + point = p1 + t * first; + second = 0; + } + + + template<int D> + double LineSeg<D> :: Length () const + { + return Dist (p1, p2); + } + + + template<int D> + void LineSeg<D> :: 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<int D> + void LineSeg<D> :: LineIntersections (const double a, const double b, const double c, + Array < Point<D> > & 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<int D> + void LineSeg<D> :: Project (const Point<D> point, Point<D> & point_on_curve, double & t) const + { + Vec<D> 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<int D> + void LineSeg<D> :: GetRawData (Array<double> & data) const + { + data.Append(2); + for(int i=0; i<D; i++) + data.Append(p1[i]); + for(int i=0; i<D; i++) + data.Append(p2[i]); + } + + + + + + /* + template<int D> + double SplineSeg3<D> :: MaxCurvature(void) const + { + Vec<D> v1 = p1-p2; + Vec<D> 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<int D> + CircleSeg<D> :: CircleSeg (const GeomPoint<D> & ap1, + const GeomPoint<D> & ap2, + const GeomPoint<D> & ap3) + : p1(ap1), p2(ap2), p3(ap3) + { + Vec<D> v1,v2; + + v1 = p1 - p2; + v2 = p3 - p2; + + Point<D> p1t(p1+v1); + Point<D> 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<int D> + Point<D> CircleSeg<D> :: GetPoint (double t) const + { + if (t >= 1.0) { return p3; } + + double phi = StartAngle() + t*(EndAngle()-StartAngle()); + Vec<D> tmp(cos(phi),sin(phi)); + + return pm + Radius()*tmp; + } + + template<int D> + void CircleSeg<D> :: 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<int D> + DiscretePointsSeg<D> :: DiscretePointsSeg (const Array<Point<D> > & apts) + : pts (apts) + { + for(int i=0; i<D; i++) + { + p1n(i) = apts[0](i); + p2n(i) = apts.Last()(i); + } + p1n.refatpoint = 1; + p2n.refatpoint = 1; + p1n.hmax = 1e99; + p2n.hmax = 1e99; + } + + + template<int D> + DiscretePointsSeg<D> :: ~DiscretePointsSeg () + { ; } + + template<int D> + Point<D> DiscretePointsSeg<D> :: 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<D>(pts[segnr+1]-pts[segnr]); + } + + + + + + + + + + // ************************************* + // Template for B-Splines of order ORDER + // thx to Gerhard Kitzler + // ************************************* + + template<int D, int ORDER> + class BSplineSeg : public SplineSeg<D> + { + Array<Point<D> > pts; + GeomPoint<D> p1n, p2n; + Array<int> ti; + + public: + /// + BSplineSeg (const Array<Point<D> > & apts); + /// + virtual ~BSplineSeg(); + /// + virtual Point<D> GetPoint (double t) const; + /// + virtual const GeomPoint<D> & StartPI () const { return p1n; }; + /// + virtual const GeomPoint<D> & EndPI () const { return p2n; } + /// + virtual void GetCoeff (Vector & coeffs) const {;} + + virtual double MaxCurvature(void) const {return 1;} + }; + + // Constructor + template<int D,int ORDER> + BSplineSeg<D,ORDER> :: BSplineSeg (const Array<Point<D> > & apts) + : pts (apts) + { + /* + for(int i=0; i<D; i++) + { + p1n(i) = apts[0](i); + p2n(i) = apts.Last()(i); + } + */ + p1n = apts[0]; + p2n = apts.Last(); + + /* + p1n.refatpoint = 1; + p2n.refatpoint = 1; + p1n.hmax = 1e99; + p2n.hmax = 1e99; + */ + + int m=pts.Size()+ORDER; + ti.SetSize(m); + // b.SetSize(m-1); + ti=0; + // b=0.0; + for(int i=ORDER;i<m-ORDER+1;i++) + ti[i]=i-ORDER+1; + for(int i=m-ORDER+1;i<m;i++) + ti[i]=m-2*ORDER+1; + } + // Destructor + template<int D,int ORDER> + BSplineSeg<D, ORDER> :: ~BSplineSeg () + { ; } + + + // GetPoint Method...(evaluation of BSpline Curve) + template<int D,int ORDER> + Point<D> BSplineSeg<D,ORDER> :: 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<ORDER;degree++) + for (int k = 0; k <= degree; k++) + { + int j = interval_nr-degree+k; + double bnew = 0; + + if (k != 0) + bnew += (t-ti[j]) / ( ti[j+degree]-ti[j] ) * b[k-degree+ORDER-1]; + if (k != degree) + bnew += (ti[j+degree+1]-t) / ( ti[j+degree+1]-ti[j+1] ) * b[k-degree+ORDER]; + b[k-degree+ORDER-1] = bnew; + } + + Point<D> p = 0.0; + for(int i=0; i < ORDER; i++) + p += b[i] * Vec<D> (pts[i+interval_nr-ORDER+1]); + return p; + } + + + +} + + +#endif diff --git a/contrib/Netgen/libsrc/gprim/splinegeometry.cpp b/contrib/Netgen/libsrc/gprim/splinegeometry.cpp new file mode 100644 index 0000000000..580e61abaf --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/splinegeometry.cpp @@ -0,0 +1,134 @@ +/* + +2d Spline curve for Mesh generator + +*/ + + +#include <mystdlib.h> +#include <linalg.hpp> +#include <gprim.hpp> +#include "splinegeometry.hpp" + +namespace netgen +{ + + + template<int D> + SplineGeometry<D> :: ~SplineGeometry() + { + for(int i = 0; i < splines.Size(); i++) + delete splines[i]; + } + + + template<int D> + void SplineGeometry<D> :: GetRawData (Array<double> & raw_data) const + { + raw_data.Append(D); + // raw_data.Append(elto0); + + raw_data.Append(splines.Size()); + for(int i=0; i<splines.Size(); i++) + splines[i]->GetRawData(raw_data); + } + + + + template<int D> + int SplineGeometry<D> :: Load (const Array<double> & 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<D> > pts(3); + + for(int i=0; i<splines.Size(); i++) + { + int type = int(raw_data[pos]); + pos++; + + for(int j=0; j<type; j++) + for(int k=0; k<D; k++) + { + pts[j](k) = raw_data[pos]; + pos++; + } + + if (type == 2) + { + splines[i] = new LineSeg<D>(GeomPoint<D>(pts[0],1), + GeomPoint<D>(pts[1],1)); + } + else if (type == 3) + { + splines[i] = new SplineSeg3<D>(GeomPoint<D>(pts[0],1), + GeomPoint<D>(pts[1],1), + GeomPoint<D>(pts[2],1)); + } + else + throw NgException("something wrong with spline raw data"); + + } + return pos; + } + + + + + + + + + + template<int D> + void SplineGeometry<D> :: GetBoundingBox (Box<D> & box) const + { + if (!splines.Size()) + { + Point<D> auxp = 0.; + box.Set (auxp); + return; + } + + Array<Point<D> > 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<int D> + void SplineGeometry<D> :: SetGrading (const double grading) + { + elto0 = grading; + } + */ + + template<int D> + void SplineGeometry<D> :: AppendPoint (const Point<D> & p, const double reffac, const bool hpref) + { + geompoints.Append (GeomPoint<D>(p, reffac)); + geompoints.Last().hpref = hpref; + } + + + + template class SplineGeometry<2>; + template class SplineGeometry<3>; +} + + diff --git a/contrib/Netgen/libsrc/gprim/splinegeometry.hpp b/contrib/Netgen/libsrc/gprim/splinegeometry.hpp new file mode 100644 index 0000000000..d29adbc42e --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/splinegeometry.hpp @@ -0,0 +1,68 @@ +/* + + +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<D> > geompoints; + Array < SplineSeg<D>* > splines; + + DLL_HEADER ~SplineGeometry(); + + DLL_HEADER int Load (const Array<double> & raw_data, const int startpos = 0); + + DLL_HEADER void GetRawData (Array<double> & raw_data) const; + + + const Array<SplineSeg<D>*> & GetSplines () const + { return splines; } + + int GetNSplines (void) const { return splines.Size(); } + string GetSplineType (const int i) const { return splines[i]->GetType(); } + SplineSeg<D> & GetSpline (const int i) {return *splines[i];} + const SplineSeg<D> & GetSpline (const int i) const {return *splines[i];} + + DLL_HEADER void GetBoundingBox (Box<D> & box) const; + Box<D> GetBoundingBox () const + { Box<D> box; GetBoundingBox (box); return box; } + + int GetNP () const { return geompoints.Size(); } + const GeomPoint<D> & GetPoint(int i) const { return geompoints[i]; } + + // void SetGrading (const double grading); + DLL_HEADER void AppendPoint (const Point<D> & p, const double reffac = 1., const bool hpref = false); + + + void AppendSegment(SplineSeg<D> * spline) + { + splines.Append (spline); + } + }; + + + +} + +#endif // _FILE_SPLINEGEOMETRY diff --git a/contrib/Netgen/libsrc/gprim/transform3d.cpp b/contrib/Netgen/libsrc/gprim/transform3d.cpp new file mode 100644 index 0000000000..dcc4cef116 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/transform3d.cpp @@ -0,0 +1,165 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <gprim.hpp> +#include <linalg.hpp> + +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; +} +} diff --git a/contrib/Netgen/libsrc/gprim/transform3d.hpp b/contrib/Netgen/libsrc/gprim/transform3d.hpp new file mode 100644 index 0000000000..cd4124335c --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/transform3d.hpp @@ -0,0 +1,193 @@ +#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 descibed by pp + Transformation3d (const Point3d ** pp); + /// Unit tet is mapped to tet descibed 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 <int D> +class Transformation +{ + Mat<D> m; + Vec<D> v; +public: + /// + Transformation () { m = 0; v = 0; } + + /// Unit tet is mapped to tet descibed by pp + Transformation (const Point<D> * pp); + + /// translation + Transformation (const Vec<D> & translate) + { + v = translate; + m = 0; + for (int i = 0; i < D; i++) + m(i,i) = 1; + } + + // rotation with ... + Transformation (const Point<D> & 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<D> vc(c); + Transformation<D> tc(vc); + Transformation<D> tcinv(-vc); + // tc.CalcInverse (tcinv); + + Transformation<D> 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; + } + + /// + void CalcInverse (Transformation & inv) const; + + /// 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<D> & from, Point<D> & to) const + { + to = Point<D> (v + m * Vec<D>(from)); + } + + void Transform (Point<D> & p) const + { + p = Point<D> (v + m * Vec<D>(p)); + } + + + + /// transform vector, apply only linear part, not offset + void Transform (const Vec<D> & from, Vec<D> & to) const + { + to = m * from; + } +}; + +template <int D> +ostream & operator<< (ostream & ost, Transformation<D> & trans); + + +} + +#endif diff --git a/contrib/Netgen/libsrc/include/Makefile.am b/contrib/Netgen/libsrc/include/Makefile.am new file mode 100644 index 0000000000..f84db193a3 --- /dev/null +++ b/contrib/Netgen/libsrc/include/Makefile.am @@ -0,0 +1,8 @@ +noinst_HEADERS = acisgeom.hpp gprim.hpp meshing.hpp occgeom.hpp \ +visual.hpp csg.hpp incvis.hpp myadt.hpp opti.hpp geometry2d.hpp \ +linalg.hpp mydefs.hpp parallel.hpp stlgeom.hpp mystdlib.h + +include_HEADERS = nginterface.h nginterface_v2.hpp + +AM_CPPFLAGS = +METASOURCES = AUTO diff --git a/contrib/Netgen/libsrc/include/acisgeom.hpp b/contrib/Netgen/libsrc/include/acisgeom.hpp new file mode 100644 index 0000000000..491b7720db --- /dev/null +++ b/contrib/Netgen/libsrc/include/acisgeom.hpp @@ -0,0 +1,3 @@ +#ifdef ACIS +#include "../acisgeom/acisgeom.hpp" +#endif diff --git a/contrib/Netgen/libsrc/include/csg.hpp b/contrib/Netgen/libsrc/include/csg.hpp new file mode 100644 index 0000000000..ffd45ef0bf --- /dev/null +++ b/contrib/Netgen/libsrc/include/csg.hpp @@ -0,0 +1 @@ +#include "../csg/csg.hpp" diff --git a/contrib/Netgen/libsrc/include/geometry2d.hpp b/contrib/Netgen/libsrc/include/geometry2d.hpp new file mode 100644 index 0000000000..bf0965c228 --- /dev/null +++ b/contrib/Netgen/libsrc/include/geometry2d.hpp @@ -0,0 +1 @@ +#include "../geom2d/geometry2d.hpp" diff --git a/contrib/Netgen/libsrc/include/gprim.hpp b/contrib/Netgen/libsrc/include/gprim.hpp new file mode 100644 index 0000000000..1e827aaf8c --- /dev/null +++ b/contrib/Netgen/libsrc/include/gprim.hpp @@ -0,0 +1 @@ +#include "../gprim/gprim.hpp" diff --git a/contrib/Netgen/libsrc/include/incvis.hpp b/contrib/Netgen/libsrc/include/incvis.hpp new file mode 100644 index 0000000000..bd31bfccd6 --- /dev/null +++ b/contrib/Netgen/libsrc/include/incvis.hpp @@ -0,0 +1,39 @@ +// libraries for User interface: + + +#include <tcl.h> +#include <tk.h> + +#if TK_MAJOR_VERSION==8 && TK_MINOR_VERSION>=4 +#define tcl_const const +#else +#define tcl_const +#endif + + +# if defined(TOGL_AGL) || defined(TOGL_AGL_CLASSIC) +# include <OpenGL/gl.h> +# include <OpenGL/glu.h> +# else +# include <GL/gl.h> +# include <GL/glu.h> +# endif + + +#ifdef TOGL_X11 +// parallel +#define GLX_GLXEXT_PROTOTYPES +#include <GL/glx.h> +#include <GL/glxext.h> +#endif + + + +// part of OpenGL 1.2, but not in Microsoft's OpenGL 1.1 header: +// GL version sould be checked at runtime +#ifndef GL_CLAMP_TO_EDGE +#define GL_CLAMP_TO_EDGE 0x812F +#endif + + + diff --git a/contrib/Netgen/libsrc/include/linalg.hpp b/contrib/Netgen/libsrc/include/linalg.hpp new file mode 100644 index 0000000000..e96bd036c3 --- /dev/null +++ b/contrib/Netgen/libsrc/include/linalg.hpp @@ -0,0 +1 @@ +#include "../linalg/linalg.hpp" diff --git a/contrib/Netgen/libsrc/include/meshing.hpp b/contrib/Netgen/libsrc/include/meshing.hpp new file mode 100644 index 0000000000..e41a88f9f2 --- /dev/null +++ b/contrib/Netgen/libsrc/include/meshing.hpp @@ -0,0 +1 @@ +#include <../meshing/meshing.hpp> diff --git a/contrib/Netgen/libsrc/include/myadt.hpp b/contrib/Netgen/libsrc/include/myadt.hpp new file mode 100644 index 0000000000..d36bef05c1 --- /dev/null +++ b/contrib/Netgen/libsrc/include/myadt.hpp @@ -0,0 +1 @@ +#include <../general/myadt.hpp> diff --git a/contrib/Netgen/libsrc/include/mydefs.hpp b/contrib/Netgen/libsrc/include/mydefs.hpp new file mode 100644 index 0000000000..54c14eba22 --- /dev/null +++ b/contrib/Netgen/libsrc/include/mydefs.hpp @@ -0,0 +1,49 @@ +#ifndef FILE_MYDEFS +#define FILE_MYDEFS + +/**************************************************************************/ +/* File: mydefs.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 10. Mar. 98 */ +/**************************************************************************/ + +/* + defines for graphics, testmodes, ... +*/ + + +// #define DEBUG + +// Philippose - 31/01/2009 +// Hack for the Windows Version +// in Linux, "PACKAGE_VERSION" is replaced +// in the configure/make phases, with the +// right version number +#ifdef WIN32 +#define PACKAGE_VERSION "4.9.14" +#endif + + +#ifdef WIN32 + #if NGINTERFACE_EXPORTS || NGLIB_EXPORTS || nglib_EXPORTS + #define DLL_HEADER __declspec(dllexport) + #else + #define DLL_HEADER __declspec(dllimport) + #endif +#else + #define DLL_HEADER +#endif + + +#define noDEMOVERSION +#define noDEVELOP +#define noSTEP +#define noSOLIDGEOM + +#define noDEMOAPP +#define noMODELLER + +#define noSTAT_STREAM +#define noLOG_STREAM + +#endif diff --git a/contrib/Netgen/libsrc/include/mystdlib.h b/contrib/Netgen/libsrc/include/mystdlib.h new file mode 100644 index 0000000000..a3a9103aa5 --- /dev/null +++ b/contrib/Netgen/libsrc/include/mystdlib.h @@ -0,0 +1,88 @@ +#ifndef FILE_MYSTDLIB +#define FILE_MYSTDLIB + +#ifndef WIN32 +#include <config.h> +#endif + + +#include <iostream> +#include <iomanip> +#include <fstream> +#include <sstream> + + +#include <cstdlib> +#include <cstdio> +#include <cmath> +#include <cctype> +#include <ctime> +#include <cstring> +#include <climits> +#include <algorithm> + + +#include <new> +#include <string> +#include <typeinfo> + +#ifdef PARALLEL +// #undef SEEK_SET +// #undef SEEK_CUR +// #undef SEEK_END +#include <mpi.h> +#endif + +#ifdef _OPENMP +#include <omp.h> +#endif + + +/* +#ifdef METIS +namespace metis { extern "C" { +#include <metis.h> +} } +#endif +*/ + + +#ifndef NO_PARALLEL_THREADS +#ifndef WIN32 +#include <pthread.h> +#endif +#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 +# include <pthread.h> +# else +# include <afxwin.h> +# include <afxmt.h> +# endif // MSVC_EXPRESS +# endif +# include <windows.h> +# undef WIN32_LEAN_AND_MEAN +# include <winnt.h> + +#else // Not using MC VC++ + +# ifndef NO_PARALLEL_THREADS +# include <pthread.h> +# endif + +#endif + + +using namespace std; + +#endif + diff --git a/contrib/Netgen/libsrc/include/nginterface.h b/contrib/Netgen/libsrc/include/nginterface.h new file mode 100644 index 0000000000..85ae8d6d78 --- /dev/null +++ b/contrib/Netgen/libsrc/include/nginterface.h @@ -0,0 +1,510 @@ +#ifndef NGINTERFACE +#define NGINTERFACE + + + + + +/**************************************************************************/ +/* File: nginterface.h */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Nov. 99 */ +/**************************************************************************/ + +/* + 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 + #define DLL_HEADER +#endif + + +// max number of nodes per element +#define NG_ELEMENT_MAXPOINTS 12 + +// max number of nodes per surface element +#define NG_SURFACE_ELEMENT_MAXPOINTS 8 + + + +// implemented element types: +enum NG_ELEMENT_TYPE { + NG_SEGM = 1, NG_SEGM3 = 2, + NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, + NG_TET = 20, NG_TET10 = 21, + NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, + NG_HEX = 25 +}; + +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 geomtry from file + DLL_HEADER void Ng_LoadGeometry (const char * filename); + + // load netgen mesh + DLL_HEADER void Ng_LoadMesh (const char * filename); + + // 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 char * Ng_GetElementMaterial (int ei); + + // Get Material of domain dom + DLL_HEADER 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 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 elment ei curved ? + DLL_HEADER int Ng_IsElementCurved (int ei); + // is elment sei curved ? + DLL_HEADER int Ng_IsSurfaceElementCurved (int sei); + + /// Curved Elemens: + /// 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 Elemens: + /// 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 Elemens: + /// 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 + // Is Element ei an element of this processor ?? + bool Ng_IsGhostEl (int ei); + + void Ng_SetGhostEl(const int ei, const bool aisghost ); + + bool Ng_IsGhostSEl (int ei); + + void Ng_SetGhostSEl(const int ei, const bool aisghost ); + + bool Ng_IsGhostVert ( int pnum ); + bool Ng_IsGhostEdge ( int ednum ); + bool Ng_IsGhostFace ( int fanum ); + + bool Ng_IsExchangeEl ( int elnum ); + bool Ng_IsExchangeSEl ( int selnr ); + + void Ng_UpdateOverlap (); + int Ng_Overlap(); +/* void Ng_SetGhostVert ( const int pnum, const bool aisghost ); */ +/* void Ng_SetGhostEdge ( const int ednum, const bool aisghost ); */ +/* void Ng_SetGhostFace ( const int fanum, const bool aisghost ); */ + + + + + // the folling functions are 0-base !! + int NgPar_GetLoc2Glob_VolEl ( int locnum ); + + // int NgPar_GetDistantNodeNums ( int nt, int locnum, int * procs, int * distnum); + + // number on distant processor + + // gibt anzahl an distant pnums zurueck + // * pnums entspricht ARRAY<int[2] > + int NgPar_GetDistantNodeNums ( int nodetype, int locnum, int * pnums ); + int NgPar_GetNDistantNodeNums ( int nodetype, int locnum ); + + int NgPar_GetDistantPNum ( int proc, int locnum ) ; + int NgPar_GetDistantEdgeNum ( int proc, int locnum ) ; + int NgPar_GetDistantFaceNum ( int proc, int locnum ) ; + int NgPar_GetDistantElNum ( int proc, int locnum ); + + bool NgPar_IsExchangeFace ( int fnr ) ; + bool NgPar_IsExchangeVert ( int vnum ); + bool NgPar_IsExchangeEdge ( int ednum ); + bool NgPar_IsExchangeElement ( int elnum ); + + void NgPar_PrintParallelMeshTopology (); + bool NgPar_IsElementInPartition ( int elnum, int dest ); + + bool NgPar_IsGhostFace ( int facenum ); + bool NgPar_IsGhostEdge ( int edgenum ); + + +#endif + + namespace netgen { + // #include "../visualization/soldata.hpp" + class SolutionData; + } + + 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 + { + const char * 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(); + // + 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); + +#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 <iostream> +namespace netgen +{ + DLL_HEADER extern std::ostream * testout; + DLL_HEADER extern int printmessage_importance; +} + +#endif + diff --git a/contrib/Netgen/libsrc/include/nginterface_v2.hpp b/contrib/Netgen/libsrc/include/nginterface_v2.hpp new file mode 100644 index 0000000000..957b7b4dce --- /dev/null +++ b/contrib/Netgen/libsrc/include/nginterface_v2.hpp @@ -0,0 +1,175 @@ +#ifndef NGINTERFACE_V2 +#define NGINTERFACE_V2 + + +/**************************************************************************/ +/* File: nginterface_v2.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: May 09 */ +/**************************************************************************/ + +/* + C++ interface to Netgen +*/ + + +namespace netgen +{ + class Ng_Element + { + + class Ng_Points + { + public: + int num; + const int * ptr; + + int Size() const { return num; } + int operator[] (int i) const { return ptr[i]-1; } + }; + + + class Ng_Vertices + { + public: + int num; + const int * ptr; + + int Size() const { return num; } + int operator[] (int i) const { return ptr[i]-1; } + }; + + class Ng_Edges + { + public: + int num; + const int * ptr; + + int Size() const { return num; } + int operator[] (int i) const { return abs (ptr[i])-1; } + }; + + class Ng_Faces + { + public: + int num; + const int * ptr; + + int Size() const { return num; } + int operator[] (int i) const { return (ptr[i]-1) / 8; } + }; + + public: + NG_ELEMENT_TYPE type; + NG_ELEMENT_TYPE GetType() const { return type; } + + Ng_Points points; // all points + Ng_Vertices vertices; + Ng_Edges edges; + Ng_Faces faces; + }; + + + + + template <int DIM> + DLL_HEADER int Ng_GetNElements (); + + template <int DIM> + DLL_HEADER Ng_Element Ng_GetElement (int nr); + + + + class Ng_Point + { + public: + double * pt; + double operator[] (int i) + { return pt[i]; } + }; + + DLL_HEADER Ng_Point Ng_GetPoint (int nr); + + + + + template <int DIM> class Ng_Node; + + template <> + class Ng_Node<1> + { + class Ng_Vertices + { + public: + const int * ptr; + + int Size() const { return 2; } + int operator[] (int i) const { return ptr[i]-1; } + }; + + + public: + Ng_Vertices vertices; + }; + + + + template <> + class Ng_Node<2> + { + class Ng_Vertices + { + public: + int nv; + const int * ptr; + + int Size() const { return nv; } + int operator[] (int i) const { return ptr[i]-1; } + }; + + class Ng_Edges + { + public: + int ned; + const int * ptr; + + int Size() const { return ned; } + int operator[] (int i) const { return ptr[i]-1; } + }; + + + public: + Ng_Vertices vertices; + Ng_Edges edges; + }; + + + + + template <int DIM> + DLL_HEADER Ng_Node<DIM> Ng_GetNode (int nr); + + + template <int DIM> + DLL_HEADER int Ng_GetNNodes (); + + + + + + /// Curved Elements: + /// 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 <int DIM_EL, int DIM_SPACE> + DLL_HEADER void Ng_MultiElementTransformation (int elnr, int npts, + const double * xi, size_t sxi, + double * x, size_t sx, + double * dxdxi, size_t sdxdxi); + + template <int DIM> + DLL_HEADER int Ng_GetElementIndex (int nr); +} +#endif + diff --git a/contrib/Netgen/libsrc/include/occgeom.hpp b/contrib/Netgen/libsrc/include/occgeom.hpp new file mode 100644 index 0000000000..af258e0df0 --- /dev/null +++ b/contrib/Netgen/libsrc/include/occgeom.hpp @@ -0,0 +1 @@ +#include "../occ/occgeom.hpp" diff --git a/contrib/Netgen/libsrc/include/opti.hpp b/contrib/Netgen/libsrc/include/opti.hpp new file mode 100644 index 0000000000..5792d70f2a --- /dev/null +++ b/contrib/Netgen/libsrc/include/opti.hpp @@ -0,0 +1 @@ +#include "../linalg/opti.hpp" diff --git a/contrib/Netgen/libsrc/include/parallel.hpp b/contrib/Netgen/libsrc/include/parallel.hpp new file mode 100644 index 0000000000..4ba662f810 --- /dev/null +++ b/contrib/Netgen/libsrc/include/parallel.hpp @@ -0,0 +1 @@ +#include "../parallel/parallel.hpp" diff --git a/contrib/Netgen/libsrc/include/parallelinterface.hpp b/contrib/Netgen/libsrc/include/parallelinterface.hpp new file mode 100644 index 0000000000..4fb8b8e2ec --- /dev/null +++ b/contrib/Netgen/libsrc/include/parallelinterface.hpp @@ -0,0 +1,49 @@ +gibt's nicht mehr + + +#ifndef FILE_PARALLELINTERFACE +#define FILE_PARALLELINTERFACE + +#ifdef PARALLEL + +#ifdef __cplusplus +extern "C" { +#endif + + // this interface is 0-base !! + + + int NgPar_GetLoc2Glob_VolEl ( int locnum ); + + // int NgPar_GetDistantNodeNums ( int nt, int locnum, int * procs, int * distnum); + + // number on distant processor + + // gibt anzahl an distant pnums zurueck + // * pnums entspricht ARRAY<int[2] > + int NgPar_GetDistantNodeNums ( int nodetype, int locnum, int * pnums ); + int NgPar_GetNDistantNodeNums ( int nodetype, int locnum ); + + int NgPar_GetDistantPNum ( int proc, int locnum ) ; + int NgPar_GetDistantEdgeNum ( int proc, int locnum ) ; + int NgPar_GetDistantFaceNum ( int proc, int locnum ) ; + int NgPar_GetDistantElNum ( int proc, int locnum ); + + bool NgPar_IsExchangeFace ( int fnr ) ; + bool NgPar_IsExchangeVert ( int vnum ); + bool NgPar_IsExchangeEdge ( int ednum ); + bool NgPar_IsExchangeElement ( int elnum ); + + void NgPar_PrintParallelMeshTopology (); + bool NgPar_IsElementInPartition ( int elnum, int dest ); + + bool NgPar_IsGhostFace ( int facenum ); + bool NgPar_IsGhostEdge ( int edgenum ); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/contrib/Netgen/libsrc/include/stlgeom.hpp b/contrib/Netgen/libsrc/include/stlgeom.hpp new file mode 100644 index 0000000000..f1eea264e1 --- /dev/null +++ b/contrib/Netgen/libsrc/include/stlgeom.hpp @@ -0,0 +1 @@ +#include <../stlgeom/stlgeom.hpp> diff --git a/contrib/Netgen/libsrc/include/visual.hpp b/contrib/Netgen/libsrc/include/visual.hpp new file mode 100644 index 0000000000..f026f5a458 --- /dev/null +++ b/contrib/Netgen/libsrc/include/visual.hpp @@ -0,0 +1 @@ +#include "../visualization/visual.hpp" diff --git a/contrib/Netgen/libsrc/interface/Makefile.am b/contrib/Netgen/libsrc/interface/Makefile.am new file mode 100644 index 0000000000..013797957c --- /dev/null +++ b/contrib/Netgen/libsrc/interface/Makefile.am @@ -0,0 +1,12 @@ +noinst_HEADERS = writeuser.hpp + +AM_CPPFLAGS = -I$(top_srcdir)/libsrc/include -I$(top_srcdir)/libsrc/interface $(MPI_INCLUDES) $(TCL_INCLUDES) -DOPENGL +METASOURCES = AUTO +lib_LTLIBRARIES = libinterface.la +libinterface_la_SOURCES = 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 + + diff --git a/contrib/Netgen/libsrc/interface/nginterface.cpp b/contrib/Netgen/libsrc/interface/nginterface.cpp new file mode 100644 index 0000000000..a5f7e7a145 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/nginterface.cpp @@ -0,0 +1,2448 @@ +#include <mystdlib.h> + +#include <meshing.hpp> +#include <csg.hpp> + + +#ifdef SOCKETS +#include "../sockets/sockets.hpp" +#endif + +#ifndef NOTCL +#include <visual.hpp> +#endif + + +#include "nginterface.h" +#include "../visualization/soldata.hpp" + + +#ifdef _MSC_VER +// Philippose - 30/01/2009 +// MSVC Express Edition Support +#ifdef MSVC_EXPRESS + +// #include <pthread.h> + + static pthread_t meshingthread; + void RunParallel ( void * (*fun)(void *), void * in) + { + if (netgen::mparam.parthread) // && (ntasks == 1) ) + { + pthread_attr_t attr; + pthread_attr_init (&attr); + // the following call can be removed if not available: + pthread_attr_setstacksize(&attr, 1000000); + //pthread_create (&meshingthread, &attr, fun, NULL); + pthread_create (&meshingthread, &attr, fun, in); + } + else + fun (in); + } + +#else // Using MS VC++ Standard / Enterprise / Professional edition + + // Afx - Threads need different return - value: + + static void* (*sfun)(void *); + unsigned int fun2 (void * val) + { + sfun (val); + return 0; + } + + void RunParallel ( void* (*fun)(void *), void * in) + { + sfun = fun; + if (netgen::mparam.parthread) + AfxBeginThread (fun2, in); + //AfxBeginThread (fun2, NULL); + else + fun (in); + } + +#endif // #ifdef MSVC_EXPRESS + +#else // For #ifdef _MSC_VER + +// #include <pthread.h> + + static pthread_t 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) + { + pthread_attr_t attr; + pthread_attr_init (&attr); + // the following call can be removed if not available: + pthread_attr_setstacksize(&attr, 1000000); + //pthread_create (&meshingthread, &attr, fun, NULL); + pthread_create (&meshingthread, &attr, fun, in); + } + else + fun (in); + } + +#endif // #ifdef _MSC_VER + + + + + + +namespace netgen +{ +#include "writeuser.hpp" + + MeshingParameters mparam; + + // global variable mesh (should not be used in libraries) + AutoPtr<Mesh> mesh; + NetgenGeometry * ng_geometry = new NetgenGeometry; + + // extern NetgenGeometry * ng_geometry; + // extern AutoPtr<Mesh> mesh; + +#ifndef NOTCL + extern Tcl_Interp * tcl_interp; +#endif + + +#ifdef OPENGL + extern VisualSceneSolution vssolution; +#endif + extern CSGeometry * ParseCSG (istream & istr); + +#ifdef SOCKETS + extern AutoPtr<ClientSocket> clientsocket; + //extern Array< AutoPtr < ServerInfo > > servers; + extern Array< ServerInfo* > servers; +#endif + + +} + + +using namespace netgen; + + +void Ng_LoadGeometry (const char * filename) +{ + + for (int i = 0; i < geometryregister.Size(); i++) + { + NetgenGeometry * hgeom = geometryregister[i]->Load (filename); + if (hgeom) + { + delete ng_geometry; + ng_geometry = hgeom; + + mesh.Reset(); + return; + } + } + + // he: if filename is empty, return + // can be used to reset geometry + if (strcmp(filename,"")==0) + { + delete ng_geometry; + ng_geometry = new NetgenGeometry(); + return; + } + + cerr << "cannot load geometry '" << filename << "'" << endl; +} + + +void Ng_LoadMeshFromStream ( istream & input ) +{ + mesh.Reset (new Mesh()); + mesh -> Load(input); + + for (int i = 0; i < geometryregister.Size(); i++) + { + NetgenGeometry * hgeom = geometryregister[i]->LoadFromMeshFile (input); + if (hgeom) + { + delete ng_geometry; + ng_geometry = hgeom; + break; + } + } + + +#ifdef LOADOLD + if(input.good()) + { + string auxstring; + input >> auxstring; + if(auxstring == "csgsurfaces") + { + /* + if (geometry) + { + geometry.Reset (new CSGeometry ("")); + } + if (stlgeometry) + { + delete stlgeometry; + stlgeometry = NULL; + } + #ifdef OCCGEOMETRY + if (occgeometry) + { + delete occgeometry; + occgeometry = NULL; + } + #endif + #ifdef ACIS + if (acisgeometry) + { + delete acisgeometry; + acisgeometry = NULL; + } + #endif + geometry2d.Reset (0); + */ + // geometry -> LoadSurfaces(input); + CSGeometry * geometry = new CSGeometry (""); + geometry -> LoadSurfaces(input); + + delete ng_geometry; + ng_geometry = geometry; + } + } +#endif +} + + + + +void Ng_LoadMesh (const char * filename) +{ + if ( (strlen (filename) > 4) && + strcmp (filename + (strlen (filename)-4), ".vol") != 0 ) + { + mesh.Reset (new Mesh()); + ReadFile(*mesh,filename); + + //mesh->SetGlobalH (mparam.maxh); + //mesh->CalcLocalH(); + return; + } + + ifstream infile(filename); + Ng_LoadMeshFromStream(infile); +} + +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 + { + int i; + const Element2d & el = mesh->SurfaceElement (ei); + for (i = 0; i < el.GetNP(); i++) + epi[i] = el.PNum(i+1); + + if (np) *np = el.GetNP(); + return NG_ELEMENT_TYPE (el.GetType()); + /* + switch (el.GetNP()) + { + case 3: return NG_TRIG; + case 4: return NG_QUAD; + case 6: return NG_TRIG6; + } + */ + } + + // 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); +} + +char * Ng_GetElementMaterial (int ei) +{ + static char empty[] = ""; + if (mesh->GetDimension() == 3) + { + int ind = mesh->VolumeElement(ei).GetIndex(); + // cout << "ind = " << ind << endl; + const char * mat = mesh->GetMaterial (ind); + if (mat) + return const_cast<char*> (mat); + else + return empty; + } + // add astrid + else + { + int ind = mesh->SurfaceElement(ei).GetIndex(); + ind = mesh->GetFaceDescriptor(ind).BCProperty(); + const char * mat = mesh->GetMaterial ( ind ); + if (mat) + return const_cast<char*> (mat); + else + return empty; + } + return 0; +} + +char * Ng_GetDomainMaterial (int dom) +{ + static char empty[] = ""; + // astrid + if ( 1 ) // mesh->GetDimension() == 3) + { + const char * mat = mesh->GetMaterial(dom); + if (mat) + return const_cast<char*> (mat); + else + return empty; + } + + return 0; +} + +int Ng_GetUserDataSize (char * id) +{ + Array<double> da; + mesh->GetUserData (id, da); + return da.Size(); +} + +void Ng_GetUserData (char * id, double * data) +{ + Array<double> 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<char *>(mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).GetBCName().c_str()); + else + return const_cast<char *>(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<char *>(mesh->GetBCName(bcnr).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<OCCGeometry*> (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<CSGeometry*> (ng_geometry); + 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<int> * dummy(NULL); + int ind = -1; + + if(indices != NULL) + { + dummy = new Array<int>(numind); + for(int i=0; i<numind; i++) (*dummy)[i] = indices[i]; + } + + if (mesh->GetDimension() == 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<int> * dummy(NULL); + int ind = -1; + + if(indices != NULL) + { + dummy = new Array<int>(numind); + for(int i=0; i<numind; i++) (*dummy)[i] = indices[i]; + } + + if (mesh->GetDimension() == 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) +{ + 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); + } + } + } +} + + +#ifdef OLD +void Ng_GetBufferedElementTransformation (int ei, const double * xi, + double * x, double * dxdxi, + void * buffer, int buffervalid) +{ + // buffer = 0; + // buffervalid = 0; + if (mesh->GetDimension() == 2) + { + return Ng_GetElementTransformation (ei, xi, x, dxdxi); + } + else + { + mesh->GetCurvedElements().CalcElementTransformation (reinterpret_cast<const Point<3> &> (*xi), + ei-1, + reinterpret_cast<Point<3> &> (*x), + reinterpret_cast<Mat<3,3> &> (*dxdxi), + buffer, (buffervalid != 0)); + + /* + Point<3> xl(xi[0], xi[1], xi[2]); + Point<3> xg; + Mat<3,3> dx; + // buffervalid = 0; + mesh->GetCurvedElements().CalcElementTransformation (xl, ei-1, xg, dx, buffer, buffervalid); + + // still 1-based arrays + 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); + } + } + */ + } +} +#endif + + + + + + +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 +// Is Element ei an element of this processor ?? +bool Ng_IsGhostEl (int ei) +{ + return false; + /* + if ( mesh->GetDimension() == 3 ) + return mesh->VolumeElement(ei).IsGhost(); + else + return false; + */ +} + +void Ng_SetGhostEl(const int ei, const bool aisghost ) +{ + ; + /* + if ( mesh -> GetDimension () == 3 ) + mesh -> VolumeElement(ei).SetGhost (aisghost); + */ +} + +bool Ng_IsGhostSEl (int ei) +{ + return false; + /* + if ( mesh -> GetDimension () == 3 ) + return mesh->SurfaceElement(ei).IsGhost(); + else + return false; + */ +} + +void Ng_SetGhostSEl(const int ei, const bool aisghost ) +{ + ; + /* + if ( mesh -> GetDimension () == 3 ) + mesh -> SurfaceElement(ei).SetGhost (aisghost); + */ +} + + +bool Ng_IsGhostVert ( int pnum ) +{ + return false; + // return mesh -> Point ( pnum ).IsGhost() ; +} +bool Ng_IsGhostEdge ( int ednum ) +{ + return false; + // return mesh -> GetParallelTopology() . IsGhostEdge ( ednum ); +} + +bool Ng_IsGhostFace ( int fanum ) +{ + return false; + // return mesh -> GetParallelTopology() . IsGhostFace ( fanum ); +} + +// void Ng_SetGhostVert ( const int pnum, const bool aisghost ); +// void Ng_SetGhostEdge ( const int ednum, const bool aisghost ); +// void Ng_SetGhostFace ( const int fanum, const bool aisghost ); + + +bool Ng_IsExchangeEl ( int elnum ) +{ return mesh -> GetParallelTopology() . IsExchangeElement ( elnum ); } + +bool Ng_IsExchangeSEl ( int selnum ) +{ return mesh -> GetParallelTopology() . IsExchangeSEl ( selnum ); } + +void Ng_UpdateOverlap() +{ + ; // mesh->UpdateOverlap(); +} + +int Ng_Overlap () +{ + return 0; + // return mesh->GetParallelTopology() . Overlap(); +} + + + + int NgPar_GetLoc2Glob_VolEl ( int locnum ) + { + return mesh -> GetParallelTopology().GetLoc2Glob_VolEl ( locnum+1) -1; + } + + // gibt anzahl an distant pnums zurueck + // * pnums entspricht ARRAY<int[2] > + int NgPar_GetDistantNodeNums ( int nodetype, int locnum, int * distnums ) + { + int size; + switch ( nodetype ) + { + case 0: + size = mesh->GetParallelTopology().GetDistantPNums( locnum+1, distnums ); + break; + case 1: + size = mesh->GetParallelTopology().GetDistantEdgeNums( locnum+1, distnums ); + break; + case 2: + size = mesh->GetParallelTopology().GetDistantFaceNums( locnum+1, distnums ); + break; + case 3: + size = mesh->GetParallelTopology().GetDistantElNums( locnum+1, distnums ); + break; + default: + cerr << "NgPar_GetDistantNodeNums() Unknown nodetype " << nodetype << endl; + size = -1; + } + // 0 - based + for ( int i = 0; i < size; i++ ) + distnums[2*i+1]--; + + return size; + } + + int NgPar_GetNDistantNodeNums ( int nodetype, int locnum ) + { + switch ( nodetype ) + { + case 0: + return mesh->GetParallelTopology().GetNDistantPNums( locnum+1 ); + case 1: + return mesh->GetParallelTopology().GetNDistantEdgeNums( locnum+1 ); + case 2: + return mesh->GetParallelTopology().GetNDistantFaceNums( locnum+1 ); + case 3: + return mesh->GetParallelTopology().GetNDistantElNums( locnum+1 ); + } + return -1; + } + + int NgPar_GetDistantPNum ( int proc, int locpnum ) + { + return mesh->GetParallelTopology().GetDistantPNum( proc, locpnum+1) - 1; + } + + int NgPar_GetDistantEdgeNum ( int proc, int locpnum ) + { + return mesh->GetParallelTopology().GetDistantEdgeNum( proc, locpnum+1) - 1; + } + + int NgPar_GetDistantFaceNum ( int proc, int locpnum ) + { + return mesh->GetParallelTopology().GetDistantFaceNum (proc, locpnum+1 ) - 1; + } + + int NgPar_GetDistantElNum ( int proc, int locelnum ) + { + return mesh->GetParallelTopology().GetDistantElNum (proc, locelnum+1 ) - 1; + } + + bool NgPar_IsExchangeFace ( int fnr ) + { + return (mesh->GetParallelTopology().GetNDistantFaceNums( fnr+1 ) > 0); + // return mesh->GetParallelTopology().IsExchangeFace ( fnr+1 ); + } + + bool NgPar_IsExchangeVert ( int vnum ) + { + return (mesh->GetParallelTopology().GetNDistantPNums( vnum+1 ) > 0); + // return mesh->GetParallelTopology().IsExchangeVert ( vnum+1 ); + } + + bool NgPar_IsExchangeEdge ( int ednum ) + { + return (mesh->GetParallelTopology().GetNDistantEdgeNums( ednum+1 ) > 0); + // return mesh->GetParallelTopology().IsExchangeEdge ( ednum+1 ); + } + + bool NgPar_IsExchangeElement ( int elnum ) + { + return (mesh->GetParallelTopology().GetNDistantElNums( elnum+1 ) > 0); + // return mesh->GetParallelTopology().IsExchangeElement ( elnum+1 ); + } + + + void NgPar_PrintParallelMeshTopology () + { + mesh -> GetParallelTopology().Print (); + } + + +#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 = ng_geometry->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<Refinement&> (ng_geometry->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<Refinement&> (ng_geometry -> GetRefinement()); + HPRefinement (*mesh, &ref, 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, parameter, setorders, ref_level); + */ +} + + +void Ng_HighOrder (int order, bool rational) +{ + NgLock meshlock (mesh->MajorMutex(), true); + /* + Refinement * ref; + + 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); + } + #endif + else if (geometry2d) + ref = new Refinement2d (*geometry2d); + else + { + ref = new RefinementSurfaces (*geometry); + } + */ + // cout << "parameter 1: " << argv[1] << " (conversion to int = " << atoi(argv[1]) << ")" << endl; + + + mesh -> GetCurvedElements().BuildCurvedElements (&const_cast<Refinement&> (ng_geometry -> GetRefinement()), + order, rational); + mesh -> SetNextMajorTimeStamp(); + + /* + if(mesh) + mesh -> GetCurvedElements().BuildCurvedElements (ref, order, rational); + */ + + // delete ref; +} + + + + + + + + + + + + +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.Ptr(); + mesh.Ptr() = (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<int> 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<int,4> 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<int,4> 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) +{ + if (mesh->GetDimension() == 3) + return mesh->GetTopology().GetVertexElements(vnr).Size(); + else + return mesh->GetTopology().GetVertexSurfaceElements(vnr).Size(); +} + +void Ng_GetVertexElements (int vnr, int * els) +{ + FlatArray<int> ia(0,0); + if (mesh->GetDimension() == 3) + ia = mesh->GetTopology().GetVertexElements(vnr); + else + ia = mesh->GetTopology().GetVertexSurfaceElements(vnr); + for (int i = 0; i < ia.Size(); i++) + els[i] = ia[i]; +} + + +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<INDEX_2> 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<INDEX_2> 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<INDEX,PointIndex::BASE> 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 = map[(*mesh)[si][0]]; + PointIndex other2 = 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<INDEX,PointIndex::BASE> 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 = map[(*mesh)[si][0]]; + PointIndex other2 = 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<int,4> indexArray; + topology.GetVertexElements( vnr, indexArray ); + + for( int i=0; i<indexArray.Size(); i++ ) + elems[i] = indexArray[i]; + + return indexArray.Size(); +} + +///// Added by Roman Stainko .... +int Ng_GetVertex_SurfaceElements( int vnr, int* elems ) +{ + const MeshTopology& topology = mesh->GetTopology(); + ArrayMem<int,4> indexArray; + topology.GetVertexSurfaceElements( vnr, indexArray ); + + for( int i=0; i<indexArray.Size(); i++ ) + elems[i] = indexArray[i]; + + return indexArray.Size(); +} + +///// Added by Roman Stainko .... +int Ng_GetVertex_NElements( int vnr ) +{ + const MeshTopology& topology = mesh->GetTopology(); + ArrayMem<int,4> indexArray; + topology.GetVertexElements( vnr, indexArray ); + + return indexArray.Size(); +} + +///// Added by Roman Stainko .... +int Ng_GetVertex_NSurfaceElements( int vnr ) +{ + const MeshTopology& topology = mesh->GetTopology(); + ArrayMem<int,4> indexArray; + topology.GetVertexSurfaceElements( vnr, indexArray ); + + return indexArray.Size(); +} + + + +#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<Refinement*> (&ng_geometry -> 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); + CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry); + if (geometry) + { + opt = new MeshOptimize2dSurfaces(*geometry); + ref->Set2dOptimizer(opt); + } + } + + if(!mesh->LocalHFunctionGenerated()) + mesh->CalcLocalH(mparam.grading); + + mesh->LocalHFunction().SetGrading (mparam.grading); + + Array<double> * qualityloss_arr = NULL; + if(qualityloss != NULL) + qualityloss_arr = new Array<double>; + + ref -> Bisect (*mesh, biopt, qualityloss_arr); + + int retval = 0; + + if(qualityloss != NULL) + { + *qualityloss = new double[qualityloss_arr->Size()+1]; + + for(int i = 0; i<qualityloss_arr->Size(); 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; +} diff --git a/contrib/Netgen/libsrc/interface/nginterface_v2.cpp b/contrib/Netgen/libsrc/interface/nginterface_v2.cpp new file mode 100644 index 0000000000..f59d61130c --- /dev/null +++ b/contrib/Netgen/libsrc/interface/nginterface_v2.cpp @@ -0,0 +1,221 @@ +#include <mystdlib.h> +#include <meshing.hpp> + + + +#ifdef SOCKETS +#include "../sockets/sockets.hpp" +#endif + +#ifndef NOTCL +#include <visual.hpp> +#endif + + +#include "nginterface.h" +#include "nginterface_v2.hpp" + + + +namespace netgen +{ +#include "writeuser.hpp" + + extern AutoPtr<Mesh> mesh; +} + + + +namespace netgen +{ + + + + 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<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; + } + + + 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 <> + DLL_HEADER void Ng_MultiElementTransformation<3,3> (int elnr, int npts, + const double * xi, size_t sxi, + double * x, size_t sx, + double * dxdxi, size_t sdxdxi) + { + mesh->GetCurvedElements().CalcMultiPointElementTransformation (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi); + } + + template <> + DLL_HEADER void Ng_MultiElementTransformation<2,2> (int elnr, int npts, + const double * xi, size_t sxi, + double * x, size_t sx, + double * dxdxi, size_t sdxdxi) + { + mesh->GetCurvedElements().CalcMultiPointSurfaceTransformation<2> (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi); + } + + template <> + DLL_HEADER void Ng_MultiElementTransformation<2,3> (int elnr, int npts, + const double * xi, size_t sxi, + double * x, size_t sx, + double * dxdxi, size_t sdxdxi) + { + mesh->GetCurvedElements().CalcMultiPointSurfaceTransformation<3> (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi); + } + + template <> + DLL_HEADER void Ng_MultiElementTransformation<1,2> (int elnr, int npts, + const double * xi, size_t sxi, + double * x, size_t sx, + double * dxdxi, size_t sdxdxi) + { + mesh->GetCurvedElements().CalcMultiPointSegmentTransformation<2> (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi); + } + + template <> + DLL_HEADER void Ng_MultiElementTransformation<1,1> (int elnr, int npts, + const double * xi, size_t sxi, + double * x, size_t sx, + double * dxdxi, size_t sdxdxi) + { + cout << "1D not supported" << endl; + } + + + + template <> DLL_HEADER int Ng_GetNNodes<1> () + { + return mesh->GetTopology().GetNEdges(); + } + + template <> DLL_HEADER int Ng_GetNNodes<2> () + { + return mesh->GetTopology().GetNFaces(); + } + + template <> DLL_HEADER Ng_Node<1> Ng_GetNode<1> (int nr) + { + Ng_Node<1> node; + node.vertices.ptr = mesh->GetTopology().GetEdgeVerticesPtr(nr); + return node; + } + + template <> DLL_HEADER Ng_Node<2> Ng_GetNode<2> (int nr) + { + Ng_Node<2> node; + node.vertices.ptr = mesh->GetTopology().GetFaceVerticesPtr(nr); + node.vertices.nv = (node.vertices.ptr[3] == 0) ? 3 : 4; + return node; + } + +} + + +int link_it_nginterface_v2; + diff --git a/contrib/Netgen/libsrc/interface/read_fnf_mesh.cpp b/contrib/Netgen/libsrc/interface/read_fnf_mesh.cpp new file mode 100644 index 0000000000..d1cff5fc4f --- /dev/null +++ b/contrib/Netgen/libsrc/interface/read_fnf_mesh.cpp @@ -0,0 +1,451 @@ + +// +// Read Pro/ENGINEER neutral format +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> +#include <sys/stat.h> + + +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<double> 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; + cout << "Title: " << name << endl; + } + else if (token == "%STATISTICS") + { + ; + } + else if (token == "%END_SECT") + { + break; + } + else + { + cout << "SECTION HEADER, unknown field: " << buf << endl; + } + } + } + + + 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 + { + cout << "SECTION ELEM_TYPE, unknown field: " << buf << endl; + } + } + } + + + 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 == "MATERIALS") + { + *testout << "parse materials" << endl; + Array<double> 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 + { + cout << "SECTION MATERIALS, unknown field: " << buf << endl; + } + } + } + + + 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<int> 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 + { + cout << "SECTION MESH, unknown: " << buf << endl; + } + } + } + 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<int> 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<int> 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); + Element2d el2d; + el.GetFace (fnr, el2d); + el2d.SetIndex (nr); + + mesh.AddSurfaceElement (el2d); + } + } + } + else if (token == "%END_SECT") + { + break; + } + else + { + cout << "SECTION MESH, unknown: " << buf << endl; + } + } + } + + + + + else if (token == "LOADS") + { + Array<LoadType*> 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") + cout << "loadtype DISPLACEMENT found" << endl; + + if (lt->placement != "FACE" && lt->placement != "EDGE" && lt->placement != "NODE") + cout << "unsupported placement " << lt->placement << endl; + + 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 == "%END_SECT") + { + for (int i = 0; i < loadtypes.Size(); i++) + { + if (loadtypes[i]->placement == "FACE" && loadtypes[i]->name == "DISPLACEMENT") + { + mesh.SetUserData ("CONSTRAINT_DISP_FACE", loadtypes[i]->places); + cout << "constrained faces: " << loadtypes[i]->places << endl; + } + if (loadtypes[i]->placement == "EDGE" && loadtypes[i]->name == "DISPLACEMENT") + { + mesh.SetUserData ("CONSTRAINT_DISP_EDGE", loadtypes[i]->places); + cout << "constrained edges: " << loadtypes[i]->places << endl; + } + if (loadtypes[i]->placement == "NODE" && loadtypes[i]->name == "DISPLACEMENT") + { + mesh.SetUserData ("CONSTRAINT_DISP_NODE", loadtypes[i]->places); + cout << "constrained nodes: " << loadtypes[i]->places << endl; + } + } + break; + } + else + { + cout << "SECTION LOADS, unknown field: " << buf << endl; + } + } + } + + + + else + { + cout << "unknown section " << token << endl; + } + } + else + cout << "parse line: (" << buf << ")" << endl; + } + } +} diff --git a/contrib/Netgen/libsrc/interface/readtetmesh.cpp b/contrib/Netgen/libsrc/interface/readtetmesh.cpp new file mode 100644 index 0000000000..1258068b9d --- /dev/null +++ b/contrib/Netgen/libsrc/interface/readtetmesh.cpp @@ -0,0 +1,797 @@ + +// +// Read CST file format +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> +#include <sys/stat.h> + + +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<int> eldom; + int minId3D = -1, minId2D = -1; + int maxId3D(-1), maxId2D(-1), maxId1D(-1), maxId0D(-1); + Array<Array<int> *> segmentdata; + Array<Element2d* > tris; + + Array<int> userdata_int; // just save data for 1:1 output + Array<double> userdata_double; + Array<int> point_pids; + Array<int> tetfacedata; + Array<int> 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<nnodes; i++) + { + in >> 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<nperiodicmasternodes; i++) + { + for(int j=0; j<2; j++) + in >> 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<ncornerperiodicmasternodes; i++) + { + for(int j=0; j<4; j++) + in >> 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<ncubicperiodicmasternodes; i++) + { + for(int j=0; j<8; j++) + in >> 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<nedges; i++) + { + segmentdata[i] = new Array<int>(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<nperiodicmasteredges; i++) + in >> 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<ncornerperiodicmasteredges; i++) + { + in >> 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<nfaces; i++) + { + int trinum; + int segnum; + + tris.Append(new Element2d(TRIG)); + + in >> 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"<<trinum <<")" << endl; + // } + //mesh.AddSurfaceElement(tri); + + for(int j=0; j<3; j++) + { + if(neg[j]) + { + (*segmentdata[segnum_ng[j]])[4] = faceid; + (*segmentdata[segnum_ng[j]])[6] = trinum; + } + else + { + (*segmentdata[segnum_ng[j]])[3] = faceid; + (*segmentdata[segnum_ng[j]])[5] = trinum; + } + } + } + else + nullstarted = true; + } + } + break; + + case 20: + // Number of Periodic Master Faces + in >> 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<nperiodicmasterfaces; i++) + { + int tri1,tri2,transl; + Array<PointIndex> nodes1(3),nodes2(3); + Array<double> 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<nelts; i++) + { + if(int(100.*i/nelts) % 5 == 0) + cout << int(100.*i/nelts) +#ifdef WIN32 + << "%%\r" +#else + << "\%\r" +#endif + << flush; + in >> 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<int> indextodescriptor(maxId2D+1); + + // for(int i=1; i<=mesh.GetNFD(); i++) + // indextodescriptor[mesh.GetFaceDescriptor(i).SurfNr()] = i; + + + // for(SurfaceElementIndex i=0; i<mesh.GetNSE(); i++) + // mesh[i].SetIndex(indextodescriptor[mesh[i].GetIndex()]); + } + break; + + case 23: + // ElemID, NodeID0, NodeID1, NodeID2, NodeID3 + { + cout << "read elements (2)" << endl; + Element el(TET); + for(ElementIndex i=0; i<nelts; i++) + { + in >> 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 <immediately followed by> ElemID List + { + uid_to_group_3D.SetSize(maxId3D+1); + uid_to_group_3D = -1; + for(int i=0; i<numObj3D; i++) + { + int groupid; + in >> groupid; + (*testout) << "3d groupid " << groupid << endl; + //userdata_int.Append(groupid); + int nelems; + in >> nelems; + //userdata_int.Append(nelems); + for(int j=0; j<nelems; j++) + { + in >> 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 <immediately followed by> FaceID List + { + Array<int> ports; + //int totnum = 0; + uid_to_group_2D.SetSize(maxId2D+1); + uid_to_group_2D = -1; + + for(int i=0; i<numObj2D; i++) + { + int groupid; + in >> groupid; + (*testout) << "2d groupid " << groupid << endl; + //userdata_int.Append(groupid); + int nelems; + in >> nelems; + //userdata_int.Append(nelems); + for(int j=0; j<nelems; j++) + { + in >> 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 <immediately followed by> EdgeID List + { + uid_to_group_1D.SetSize(maxId1D+1); + uid_to_group_1D = -1; + + for(int i=0; i<numObj1D; i++) + { + int groupid; + in >> groupid; + //userdata_int.Append(groupid); + int nelems; + in >> nelems; + //userdata_int.Append(nelems); + for(int j=0; j<nelems; j++) + { + in >> 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 <immediately followed by> NodeID List + { + uid_to_group_0D.SetSize(maxId0D+1); + uid_to_group_0D = -1; + for(int i=0; i<numObj0D; i++) + { + int groupid; + in >> groupid; + //userdata_int.Append(groupid); + int nelems; + in >> nelems; + //userdata_int.Append(nelems); + for(int j=0; j<nelems; j++) + { + in >> 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<SurfaceElementIndex> surfindices(tris.Size()); + surfindices = -1; + + for(int i=0; i<tris.Size(); i++) + { + if(atof(version.c_str()) <= 1.999999) + { + if(tris[i]->GetIndex() > 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<minId3D; i++) + mesh.AddFaceDescriptor(FaceDescriptor(i,0,0,0)); + + + for(int i=0; i<tetfacedata.Size(); i+=9) + { + for(int j=0; j<4; j++) + { + SurfaceElementIndex surf = surfindices[tetfacedata[i+2*j]]; + + //if(mesh.GetNSE() <= surf) + if(surf == -1) + continue; + + if(tetfacedata[i+2*j+1] == 1) + mesh.GetFaceDescriptor(mesh[surf].GetIndex()).SetDomainOut(tetfacedata[i+8]); + else + mesh.GetFaceDescriptor(mesh[surf].GetIndex()).SetDomainIn(tetfacedata[i+8]); + + + /* + int faceind = 0; + for(int k=1; k<=mesh.GetNFD(); k++) + { + if(mesh.GetFaceDescriptor(k).SurfNr() == mesh[surf].GetIndex()) + faceind = k; + } + if(faceind) + { + if(tetfacedata[i+4+j] == 1) + mesh.GetFaceDescriptor(faceind).SetDomainOut(tetfacedata[i+8]); + else + mesh.GetFaceDescriptor(faceind).SetDomainIn(tetfacedata[i+8]); + } + else + { + if(tetfacedata[i+4+j] == 1) + faceind = mesh.AddFaceDescriptor(FaceDescriptor(mesh[surf].GetIndex(),0,tetfacedata[i+8],0)); + else + faceind = mesh.AddFaceDescriptor(FaceDescriptor(mesh[surf].GetIndex(),tetfacedata[i+8],0,0)); + mesh.GetFaceDescriptor(faceind).SetBCProperty(mesh[surf].GetIndex()); + } + */ + } + + } + + // Array<int> indextodescriptor(maxId2D+1); + + // for(int i=1; i<=mesh.GetNFD(); i++) + // indextodescriptor[mesh.GetFaceDescriptor(i).SurfNr()] = i; + + + // for(SurfaceElementIndex i=0; i<mesh.GetNSE(); i++) + // mesh[i].SetIndex(indextodescriptor[mesh[i].GetIndex()]); + + + for(int i=0; i<segmentdata.Size(); i++) + { + Segment seg; + + + if((atof(version.c_str()) <= 1.999999 && (*segmentdata[i])[2] > 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(); + + } +} + + diff --git a/contrib/Netgen/libsrc/interface/readuser.cpp b/contrib/Netgen/libsrc/interface/readuser.cpp new file mode 100644 index 0000000000..f21466af8d --- /dev/null +++ b/contrib/Netgen/libsrc/interface/readuser.cpp @@ -0,0 +1,422 @@ +// +// Read user dependent output file +// + + +#include <mystdlib.h> + + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +namespace netgen +{ +#include "writeuser.hpp" + + void ReadFile (Mesh & mesh, + const string & hfilename) + { + cout << "Read User File" << endl; + + 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)); + + + while (in.good()) + { + in >> reco; + cout << "reco = " << reco << endl; + + 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); + + cout << "p(" << pi << ") = " + << p << endl; + + mesh.AddPoint (p); + } + cout << "read " << mesh.GetNP() << " points" << endl; + } + + 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; + + cout << "fe_id = " << fe_id << " col = " << color << ", nnodes = " << nnodes << endl; + + 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 41: + { + Element2d el (TRIG); + el.SetIndex (1); + for (int j = 0; j < nnodes; j++) + el[j] = nodes[j]; + mesh.AddSurfaceElement (el); + + break; + } + case 111: + { + Element el (TET); + el.SetIndex (1); + for (int j = 0; j < nnodes; j++) + el[j] = nodes[j]; + mesh.AddVolumeElement (el); + + break; + } + } + } + } + } + + + Point3d pmin, pmax; + mesh.GetBox (pmin, pmax); + 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)); + + in >> nse; + for (i = 1; i <= nse; i++) + { + int mat; // , nelp; + in >> mat; + Element2d el (TRIG); + el.SetIndex (mat); + for (j = 1; j <= 3; j++) + in >> 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<double> 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); + } + + } + +} + diff --git a/contrib/Netgen/libsrc/interface/writeOpenFOAM15x.cpp b/contrib/Netgen/libsrc/interface/writeOpenFOAM15x.cpp new file mode 100644 index 0000000000..337e49eff1 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writeOpenFOAM15x.cpp @@ -0,0 +1,768 @@ +/*! \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 <n>(pnt_ind1 pnt_ind2 .... pnt_ind<n>) +* 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 <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> +#include <sys/stat.h> + + +namespace netgen +{ +#include "writeuser.hpp" + + // Global arrays used to maintain the owner, neighbour and face lists + // so that they are accessible across functions + static Array<int> owner_facelist; + static Array<int> owner_celllist; + static Array<int> neighbour_celllist; + static Array<int> surfelem_bclist; + static Array<INDEX_2> surfelem_lists; + + + + static void WriteOpenFOAM15xBanner(ofstream & 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(ofstream & outfile) + { + outfile << + "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n"; + } + + + + static void WriteOpenFOAM15xDividerEnd(ofstream & 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<MeshTopology&> (meshtopo).SetBuildEdges(true); + const_cast<MeshTopology&> (meshtopo).SetBuildFaces(true); + const_cast<MeshTopology&> (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<int> 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<int> 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 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 (ofstream & 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 (ofstream & 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 (ofstream & 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<int> 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 (ofstream & 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 (ofstream & 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<INDEX_3> 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) + { + bool error = false; + char casefiles[256]; + + // Make sure that the mesh data has been updated + const_cast<Mesh&> (mesh).Compress(); + const_cast<Mesh&> (mesh).CalcSurfacesOfNode(); + const_cast<Mesh&> (mesh).RebuildSurfaceElementLists(); + const_cast<Mesh&> (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 + sprintf(casefiles, "%s/constant/polyMesh/points", casename.c_str()); + ofstream outfile_pnts(casefiles); + sprintf(casefiles, "%s/constant/polyMesh/faces", casename.c_str()); + ofstream outfile_faces(casefiles); + sprintf(casefiles, "%s/constant/polyMesh/owner", casename.c_str()); + ofstream outfile_own(casefiles); + sprintf(casefiles, "%s/constant/polyMesh/neighbour", casename.c_str()); + ofstream outfile_nei(casefiles); + sprintf(casefiles, "%s/constant/polyMesh/boundary", casename.c_str()); + ofstream outfile_bnd(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); + outfile_own.close(); + 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); + outfile_nei.close(); + 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); + outfile_faces.close(); + 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); + outfile_pnts.close(); + 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); + outfile_bnd.close(); + 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"; + } + } +} + diff --git a/contrib/Netgen/libsrc/interface/writeabaqus.cpp b/contrib/Netgen/libsrc/interface/writeabaqus.cpp new file mode 100644 index 0000000000..6f2f165cb7 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writeabaqus.cpp @@ -0,0 +1,237 @@ +// +// Write Abaqus file +// +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +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<INDEX_2> 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<int> 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; +} + +} diff --git a/contrib/Netgen/libsrc/interface/writediffpack.cpp b/contrib/Netgen/libsrc/interface/writediffpack.cpp new file mode 100644 index 0000000000..82eb236dc0 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writediffpack.cpp @@ -0,0 +1,296 @@ +// +// Write diffpack file +// +// by +// Bartosz Sawicki <sawickib@ee.pw.edu.pl> +// extended by +// Jacques Lechelle <jacques.lechelle@wanadoo.fr> +// +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + + +namespace netgen +{ +#include "writeuser.hpp" + + +void WriteDiffPackFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename) +{ + // double scale = globflags.GetNumFlag ("scale", 1); + double scale = 1; + + ofstream outfile(filename.c_str()); + + if (mesh.GetDimension() == 3) + + { + // Output compatible to Diffpack grid format + // Bartosz Sawicki <sawickib@ee.pw.edu.pl> + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + Array <int> BIname; + Array <int> 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"; + + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + + outfile.width(4); + outfile << i << " ("; + outfile.width(10); + outfile << p.X()/scale << ", "; + outfile.width(9); + outfile << p.Y()/scale << ", "; + outfile.width(9); + outfile << p.Z()/scale << ") "; + + if(mesh[PointIndex(i)].Type() != INNERPOINT) + { + BCsinpoint.DeleteAll(); + for (j = 1; j <= nse; j++) + { + for (k = 1; k <= mesh.SurfaceElement(j).GetNP(); k++) + { + if(mesh.SurfaceElement(j).PNum(k)==i) + { + int BC=mesh.GetFaceDescriptor(mesh.SurfaceElement(j).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 <int> BIname; + Array <int> BCsinpoint; + int i, j, k, l; + + + outfile.precision(6); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + 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: 3\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"; + + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + + outfile.width(4); + outfile << i << " ("; + outfile.width(10); + outfile << p.X()/scale << ", "; + outfile.width(9); + outfile << p.Y()/scale << ", "; + + if(mesh[PointIndex(i)].Type() != INNERPOINT) + { + BCsinpoint.DeleteAll(); + for (j = 1; j <= nse; j++) + { + for (k = 1; k <= 2; k++) + { + if(mesh.SurfaceElement(j).PNum(k)==i) + { + int BC=mesh.GetFaceDescriptor(mesh.SurfaceElement(j).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 <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + outfile.width(5); + outfile << i << " ElmT3n2D "; + outfile.width(4); + outfile << el.GetIndex() << " "; + outfile.width(8); + outfile << el.PNum(1); + outfile.width(8); + outfile << el.PNum(3); + outfile.width(8); + outfile << el.PNum(2); + outfile << "\n"; + } + } +} +} diff --git a/contrib/Netgen/libsrc/interface/writedolfin.cpp b/contrib/Netgen/libsrc/interface/writedolfin.cpp new file mode 100644 index 0000000000..8fd9e7497a --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writedolfin.cpp @@ -0,0 +1,69 @@ +// +// Write dolfin file +// +// by +// Kent-Andre Mardal <kent-and@simula.no> + + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +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 << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" <<endl; + outfile << ""<<endl; + + outfile << "<dolfin xmlns:dolfin=\"http://www.phi.chalmers.se/dolfin/\">"<<endl; + outfile << " <mesh celltype=\"tetrahedron\" dim=\"3\">" <<endl; + outfile << " <vertices size=\""<<np<<"\">"<<endl; + for (int i = 1; i <= np; i++) { + const Point3d & p = mesh.Point(i); + outfile << " <vertex index=\""<<i-1<<"\" x=\""<<p.X()<<"\" y=\""<<p.Y()<<"\" z=\""<<p.Z()<<"\"/>"<<endl; + } + outfile << " </vertices>"<<endl; + + + + outfile << " <cells size=\""<<ne<<"\">"<<endl; + for (int i = 1; i <= ne; i++) { + const Element & el = mesh.VolumeElement(i); + + outfile << " <tetrahedron index=\""<<i-1<<"\" v0=\""<<el.PNum(1)-1<<"\" v1=\""<<el.PNum(2)-1<<"\" v2=\""<<el.PNum(3)-1<<"\" v3=\""<<el.PNum(4)-1<<"\"/>"<<endl; + } + outfile << " </cells>"<<endl; + } + outfile << " </mesh>"<<endl; + outfile << "</dolfin>"<<endl; + + cout << "done writing dolfin export" << endl; + } +} diff --git a/contrib/Netgen/libsrc/interface/writeelmer.cpp b/contrib/Netgen/libsrc/interface/writeelmer.cpp new file mode 100644 index 0000000000..664a6dadab --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writeelmer.cpp @@ -0,0 +1,132 @@ + +// +// Write Elmer file +// +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> +#include <sys/stat.h> + + +namespace netgen +{ +#include "writeuser.hpp" + + + +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<int> 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"; + } +} + +} diff --git a/contrib/Netgen/libsrc/interface/writefeap.cpp b/contrib/Netgen/libsrc/interface/writefeap.cpp new file mode 100644 index 0000000000..85681aa0cf --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writefeap.cpp @@ -0,0 +1,220 @@ +// +// Write FEAP file +// FEAP by Bob Taylor, Berkely +// +// contact Peter Wriggers or Albrecht Rieger, Hannover +// rieger@ibnm.uni-hannover.de +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +namespace netgen +{ + +#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; +} +} diff --git a/contrib/Netgen/libsrc/interface/writefluent.cpp b/contrib/Netgen/libsrc/interface/writefluent.cpp new file mode 100644 index 0000000000..c5dac392f6 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writefluent.cpp @@ -0,0 +1,193 @@ +// +// Write Fluent file +// Johannes Gerstmayr, University Linz +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +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<INDEX_3> surfaceelp; + Array<int> surfaceeli; + Array<int> 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&> (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) //dont 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; +} + +} diff --git a/contrib/Netgen/libsrc/interface/writegmsh.cpp b/contrib/Netgen/libsrc/interface/writegmsh.cpp new file mode 100644 index 0000000000..93def67783 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writegmsh.cpp @@ -0,0 +1,200 @@ +/************************************* + * 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 <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +namespace netgen +{ +#include "writeuser.hpp" + + + +/* + * GMSH mesh format + * points, elements, surface elements and physical entities + */ + +void WriteGmshFormat (const Mesh & mesh, + const CSGeometry & 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 << " Invalide element type for Gmsh volume Format !\n"; + } + + +} +} + + diff --git a/contrib/Netgen/libsrc/interface/writegmsh2.cpp b/contrib/Netgen/libsrc/interface/writegmsh2.cpp new file mode 100644 index 0000000000..5ec3dc8f0c --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writegmsh2.cpp @@ -0,0 +1,261 @@ +/*! \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 <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +namespace netgen +{ +#include "writeuser.hpp" + + // 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 CSGeometry & 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 + + diff --git a/contrib/Netgen/libsrc/interface/writejcm.cpp b/contrib/Netgen/libsrc/interface/writejcm.cpp new file mode 100644 index 0000000000..fc00955d8f --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writejcm.cpp @@ -0,0 +1,430 @@ +// +// Write JCMwave file +// 07.07.2005, Sven Burger, ZIB Berlin +// + + +#include <mystdlib.h> +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> +#include <sys/stat.h> + +namespace netgen +{ +#include "writeuser.hpp" + +void WriteJCMFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename) +{ + if (mesh.GetDimension() != 3) + { + cout <<"\n Error: Dimension 3 only supported by this output format!"<<endl; + return; + } + + int bc_at_infinity = 0; + int i, j, jj, ct(0), counter; + double dx1, dx2, dx3, dy1, dy2, dy3, dz1, dz2, dz3, vol; + + // number of points + int np = mesh.GetNP(); + + // Identic points + Array<int,1> 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"<<endl; + return; + } + + if (nprisms > 0) + cout << " Please note: Boundaries at infinity have to carry the bc-attribute '-bc=" + << bc_at_infinity <<"'."<<endl; + + // number of surface elements + int nse = mesh.GetNSE(); + // number of boundary triangles + int nbtri = 0; + // number of boundary quadrilaterals + int nbquad = 0; + // array with 1 if point on any tetra, 0 else + // this is needed in order to arrange the prism points in the right order + Array<int,1> 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(el.PNum(j).GetInt(),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 << "/* <BLOBHead>\n"; + outfile << "__BLOBTYPE__=Grid\n"; + outfile << "__OWNER__=JCMwave\n"; + outfile << "<I>SpaceDim=3\n"; + outfile << "<I>ManifoldDim=3\n"; + outfile << "<I>NRefinementSteps=0\n"; + outfile << "<I>NPoints="<<np<<"\n"; + outfile << "<I>NTetrahedra="<<ntets<<"\n"; + outfile << "<I>NPrisms="<<nprisms<<"\n"; + outfile << "<I>NBoundaryTriangles="<<nbtri<<"\n"; + outfile << "<I>NBoundaryQuadrilaterals="<<nbquad<<"\n"; + outfile << "*/\n"; + outfile << "\n"; + outfile << "# output from Netgen\n\n"; + int nDomains=mesh.GetNDomains(); + for (i=1; i<=nDomains; i++) + { + if (mesh.GetMaterial(i)) + outfile << "#" << mesh.GetMaterial(i) + << ": Material ID = " + << i << "\n"; + } + + outfile << "# Points\n"; + cout << " Please note: The unit of length in the .geo file is assumed to be 'microns'."<<endl; + for (i = 1; i <= np; i++) + { + const Point<3> & 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"<<endl; + return; + } + + outfile << "\n"; + outfile << "# Prisms\n"; + counter = 0; + for (i = 1; i <= ne; i++) + { + Element el = mesh.VolumeElement(i); + if (el.GetNP() == 6) + { + 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 (pointsOnTetras.Get(el.PNum(1)) && + pointsOnTetras.Get(el.PNum(2)) && + pointsOnTetras.Get(el.PNum(3))) + { + if (vol > 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"<<endl; + return; + } + outfile << el.GetIndex() << "\n\n"; + } + } + if ( counter != nprisms) + { + cout<< "\n Error in determining number of prisms!\n"<<endl; + return; + } + + int npid1 = 0; + int npid2 = 0; + int npid3 = 0; + for (i=1; i<=np; i++) + { + if (identmap1.Elem(i)) + npid1++; + if (identmap2.Elem(i)) + npid2++; + if (identmap3.Elem(i)) + npid3++; + } + + outfile << "\n"; + outfile << "# Boundary triangles\n"; + outfile << "# Number of identified points in 1-direction: " << npid1 << "\n"; + outfile << "# Number of identified points in 2-direction: " << npid2 << "\n"; + outfile << "# Number of identified points in 3-direction: " << npid3 << "\n"; + 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)) + { + outfile <<"# T\n"; + for (j = 1; j <= 3; j++) + outfile << el.PNum(j)<<"\n"; + if (mesh.GetFaceDescriptor (el.GetIndex()).BCProperty()==bc_at_infinity) + outfile << 1000 << "\n"; + else + outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << "\n"; + if (mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() == bc_at_infinity) + outfile << "-2\n\n"; + else if (identmap1.Elem(el.PNum(1)) + &&identmap1.Elem(el.PNum(2)) + &&identmap1.Elem(el.PNum(3))) + { + outfile << "-1\n"; + for (j = 1; j <= 3; j++) + outfile << identmap1.Elem(el.PNum(j))<<"\n"; + outfile << "\n"; + } + else if (identmap2.Elem(el.PNum(1)) + &&identmap2.Elem(el.PNum(2)) + &&identmap2.Elem(el.PNum(3))) + { + outfile << "-1\n"; + for (j = 1; j <= 3; j++) + outfile << identmap2.Elem(el.PNum(j))<<"\n"; + outfile << "\n"; + } + else if (identmap3.Elem(el.PNum(1)) + &&identmap3.Elem(el.PNum(2)) + &&identmap3.Elem(el.PNum(3))) + { + outfile << "-1\n"; + for (j = 1; j <= 3; j++) + outfile << identmap3.Elem(el.PNum(j))<<"\n"; + outfile << "\n"; + } + else + outfile << "1\n\n"; + + } + } + + outfile << "\n"; + outfile << "# Boundary quadrilaterals\n"; + for (i = 1; i <= nse; i++) + { + Element2d el = mesh.SurfaceElement(i); + + if (el.GetNP() == 4 + && (mesh.GetFaceDescriptor (el.GetIndex()).DomainIn()==0 + || mesh.GetFaceDescriptor (el.GetIndex()).DomainOut()==0)) + { + if (pointsOnTetras.Get(el.PNum(1)) && + pointsOnTetras.Get(el.PNum(2))) + ct = 0; + else if (pointsOnTetras.Get(el.PNum(2)) && + pointsOnTetras.Get(el.PNum(3))) + ct = 1; + else if (pointsOnTetras.Get(el.PNum(3)) && + pointsOnTetras.Get(el.PNum(4))) + ct = 2; + else if (pointsOnTetras.Get(el.PNum(4)) && + pointsOnTetras.Get(el.PNum(1))) + ct = 3; + else + cout << "\nWarning: Quadrilateral with inconsistent points found!"<<endl; + + for (j = 1; j <= 4; j++) + { + jj = j + ct; + if ( jj >= 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)!"<<endl; + } + else if ( identmap1.Elem(el.PNum(1)) && + identmap1.Elem(el.PNum(2)) && + identmap1.Elem(el.PNum(3)) && + identmap1.Elem(el.PNum(4)) ) + { + outfile << "-1\n"; + for (j = 1; j <= 4; j++) + { + jj = j + ct; + if ( jj >= 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; +} + +} + diff --git a/contrib/Netgen/libsrc/interface/writepermas.cpp b/contrib/Netgen/libsrc/interface/writepermas.cpp new file mode 100644 index 0000000000..fc46e87cd9 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writepermas.cpp @@ -0,0 +1,208 @@ +// +// Write Permas file +// for Intes GmbH, Stuttgart +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +#include <string> + +using namespace std; + +namespace netgen +{ +#include "writeuser.hpp" + // 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; + } + +} diff --git a/contrib/Netgen/libsrc/interface/writetecplot.cpp b/contrib/Netgen/libsrc/interface/writetecplot.cpp new file mode 100644 index 0000000000..4730b983a5 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writetecplot.cpp @@ -0,0 +1,127 @@ +// +// +// TECPLOT file by Jawor Georgiew +// +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + + + +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<int> sn(np); + ofstream outfile(filename.c_str()); + + outfile << "TITLE=\" " << filename << "\"" << endl; + + // fill hashtable + + INDEX_3_HASHTABLE<int> 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); + } + } + } +} + + +} diff --git a/contrib/Netgen/libsrc/interface/writetet.cpp b/contrib/Netgen/libsrc/interface/writetet.cpp new file mode 100644 index 0000000000..221f03013e --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writetet.cpp @@ -0,0 +1,1096 @@ + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <acisgeom.hpp> +#include <meshing.hpp> + +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<int> point_ids,edge_ids,face_ids; + Array<int> elnum(mesh.GetNE()); + elnum = -1; + + + Array<int> userdata_int; + Array<double> userdata_double; + Array<int> ports; + + Array<int> 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<mesh.GetNE(); i++) + if(i==0 || mesh[i].GetIndex() < mindomain) + mindomain = mesh[i].GetIndex(); + for(int i=1; i<=mesh.GetNFD(); i++) + if(i==1 || mesh.GetFaceDescriptor(i).BCProperty() > 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<point_ids.Size(); i++) + point_ids[i] = -1; + + + for(int i=0; i<PointIndex::BASE; i++) + point_ids[i] = -1; + + + INDEX_2_CLOSED_HASHTABLE<int> edgenumbers(6*mesh.GetNE()+3*mesh.GetNSE());; + INDEX_3_CLOSED_HASHTABLE<int> facenumbers(4*mesh.GetNE()+mesh.GetNSE()); + + Array<INDEX_2> edge2node; + Array<INDEX_3> face2edge; + Array<INDEX_4> 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<int> nodenum(point_ids.Size()+1); + + nodenum = -1; + + + + numnodes = 0; + for(int i=0; i<point_ids.Size(); i++) + { + if(point_ids[i] != -1) + { + numnodes++; + nodenum[i] = numnodes; + } + } + + + if(haveuserdata) + { + unitcode = userdata_int[pos_int]; + pos_int++; + + tolerance = userdata_double[pos_double]; + pos_double++; + + dS1 = userdata_double[pos_double]; + pos_double++; + dS2 = userdata_double[pos_double]; + pos_double++; + alphaDeg = userdata_double[pos_double]; + pos_double++; + + x3D = userdata_double[pos_double]; + pos_double++; + y3D = userdata_double[pos_double]; + pos_double++; + z3D = userdata_double[pos_double]; + pos_double++; + + if(version == 2) + { + modelverts = userdata_int[pos_int]; + pos_int++; + modeledges = userdata_int[pos_int]; + pos_int++; + modelfaces = userdata_int[pos_int]; + pos_int++; + modelcells = userdata_int[pos_int]; + pos_int++; + } + + numObj3D = userdata_int[pos_int]; + pos_int++; + numObj2D = userdata_int[pos_int]; + pos_int++; + numObj1D = userdata_int[pos_int]; + pos_int++; + numObj0D = userdata_int[pos_int]; + pos_int++; + } + else + { + unitcode = 3; + + tolerance = 1e-5; + + dS1 = dS2 = alphaDeg = 0; + + x3D = y3D = z3D = 0; + + modelverts = modeledges = modelfaces = modelcells = 0; + + numObj3D = numObj2D = numObj1D = numObj0D = 0; + } + + string uidpid; + if(version == 1) + uidpid = "PID"; + else if (version == 2) + uidpid = "UID"; + + + Array< Array<int,PointIndex::BASE>* > idmaps; + for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) + { + if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC) + { + idmaps.Append(new Array<int,PointIndex::BASE>); + mesh.GetIdentifications().GetMap(i,*idmaps.Last(),true); + } + } + + Array<int> id_num,id_type; + Array< Array<int> *> 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<mesh.GetNP()+PointIndex::BASE; i++) + { + if(id_num[i] != 0) + continue; + + if(nodenum[i] == -1) + continue; + + Array<int> group; + group.Append(i); + for(int j=0; j<idmaps.Size(); j++) + { + startsize = group.Size(); + for(int k=0; k<startsize; k++) + { + int id = (*idmaps[j])[group[k]]; + if(id != 0 && !group.Contains(id) && nodenum[id] != -1) + { + group.Append(id); + id_num[id] = j+1+id_num[group[k]]; + } + } + } + if(group.Size() > 1) + { + id_groups.Append(new Array<int>(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.Size(); j++) + id_type[group[j]] = 4; + n4++; + } + else if(group.Size() == 8) + { + id_type[i] = 5; + for(int j=1; j<group.Size(); j++) + id_type[group[j]] = 6; + n8++; + } + else + cerr << "ERROR: Identification group size = " << group.Size() << endl; + } + + } + + + for(PointIndex i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + { + if(nodenum[i] == -1) + continue; + outfile << nodenum[i] << " " + << mesh[i](0) << " " + << mesh[i](1) << " " + << mesh[i](2) << " " << id_type[i] << " "; + if(i-PointIndex::BASE < point_ids.Size()) + outfile << point_ids[i]; + else + outfile << "0"; + outfile << "\n"; + } + outfile << endl; + + outfile << "\n// Number of Periodic Master Nodes:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ + << n2 << "\n" \ + << "\n" \ + << "// MasterNodeID, SlaveNodeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2):\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<id_groups.Size(); i++) + { + if(id_groups[i]->Size() != 2) + continue; + + for(int j=0; j<id_groups[i]->Size(); j++) + outfile << nodenum[(*id_groups[i])[j]] << " "; + for(int j=1; j<id_groups[i]->Size(); 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; i<id_groups.Size(); i++) + { + if(!id_groups[i] || id_groups[i]->Size() != 4) + continue; + + for(int j=0; j<id_groups[i]->Size(); j++) + outfile << nodenum[(*id_groups[i])[j]] << " "; + for(int j=1; j<id_groups[i]->Size(); 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; i<id_groups.Size(); i++) + { + if(!id_groups[i] || id_groups[i]->Size() != 8) + continue; + + for(int j=0; j<id_groups[i]->Size(); j++) + outfile << nodenum[(*id_groups[i])[j]] << " "; + for(int j=1; j<id_groups[i]->Size(); 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), "<<uidpid<<":\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + + + + Array< Array<int>* > vertex_to_edge(mesh.GetNP()+1); + for(int i=0; i<=mesh.GetNP(); i++) + vertex_to_edge[i] = new Array<int>; + + Array< Array<int,PointIndex::BASE>* > idmaps_edge(idmaps.Size()); + for(int i=0; i<idmaps_edge.Size(); i++) + { + idmaps_edge[i] = new Array<int,PointIndex::BASE>(numedges); + (*idmaps_edge[i]) = 0; + } + + Array<int> possible; + for(int i=0; i<edge2node.Size(); i++) + { + const INDEX_2 & v = edge2node[i]; + for(int j=0; j<idmaps.Size(); j++) + { + INDEX_2 vid((*idmaps[j])[v[0]], (*idmaps[j])[v[1]]); + if(vid[0] != 0 && vid[0] != v[0] && vid[1] != 0 && vid[1] != v[1]) + { + Intersection(*vertex_to_edge[vid[0]],*vertex_to_edge[vid[1]],possible); + if(possible.Size() == 1) + { + (*idmaps_edge[j])[possible[0]] = i+1; + (*idmaps_edge[j])[i+1] = possible[0]; + } + else if(possible.Size() > 0) + { + cerr << "ERROR: too many possible edge identifications" << endl; + (*testout) << "ERROR: too many possible edge identifications" << endl + << "*vertex_to_edge["<<vid[0]<<"] " << *vertex_to_edge[vid[0]] << endl + << "*vertex_to_edge["<<vid[1]<<"] " << *vertex_to_edge[vid[1]] << endl + << "possible " << possible << endl; + } + } + } + vertex_to_edge[v[0]]->Append(i+1); + vertex_to_edge[v[1]]->Append(i+1); + } + + + for(int i=0; i<vertex_to_edge.Size(); i++) + delete vertex_to_edge[i]; + + + id_groups.SetSize(0); + id_num.SetSize(numedges+1); + id_num = 0; + id_type.SetSize(numedges+1); + id_type = 0; + + n2 = n4 = n8 = 0; + + for(int i=1; i<=edge2node.Size(); i++) + { + if(id_num[i] != 0) + continue; + + + Array<int> group; + group.Append(i); + for(int j=0; j<idmaps_edge.Size(); j++) + { + startsize = group.Size(); + for(int k=0; k<startsize; k++) + { + int id = (*idmaps_edge[j])[group[k]]; + if(id != 0 && !group.Contains(id)) + { + group.Append(id); + id_num[id] = j+1+id_num[group[k]]; + } + } + } + if(group.Size() > 1) + { + id_num[i] = 1; + id_groups.Append(new Array<int>(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.Size(); j++) + id_type[group[j]] = 4; + n4++; + } + else + { + cerr << "ERROR: edge identification group size = " << group.Size() << endl; + (*testout) << "edge group " << group << endl; + for(int j=0; j<idmaps_edge.Size(); j++) + { + (*testout) << "edge id map " << j << endl << *idmaps_edge[j] << endl; + } + } + } + } + + + + for(int i=1; i<=edge2node.Size(); i++) + { + if(id_num[i] != 0) + continue; + + + Array<int> group; + group.Append(i); + for(int j=0; j<idmaps_edge.Size(); j++) + { + startsize = group.Size(); + for(int k=0; k<startsize; k++) + { + int id = (*idmaps_edge[j])[group[k]]; + if(id != 0 && !group.Contains(id)) + { + group.Append(id); + id_num[id] = j+1+id_num[group[k]]; + } + } + } + if(group.Size() > 1) + { + id_num[i] = 1; + id_groups.Append(new Array<int>(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.Size(); j++) + id_type[group[j]] = 4; + n4++; + } + else + { + cerr << "ERROR: edge identification group size = " << group.Size() << endl; + (*testout) << "edge group " << group << endl; + for(int j=0; j<idmaps_edge.Size(); j++) + { + (*testout) << "edge id map " << j << endl << *idmaps_edge[j] << endl; + } + } + } + + } + + + for(int i=0; i<edge2node.Size(); i++) + outfile << i+1 << " " << nodenum[edge2node[i][0]] << " " << nodenum[edge2node[i][1]] + << " " << id_type[i+1] << " " << edge_ids[i] << "\n"; + + outfile << endl; + + + + outfile << "// Number of Periodic Master Edges:\n"\ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"\ + << n2 << "\n" \ + << "\n"\ + << "// MasterEdgeID, SlaveEdgeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2):\n"\ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<id_groups.Size(); i++) + { + if(id_groups[i]->Size() != 2) + continue; + + for(int j=0; j<id_groups[i]->Size(); j++) + outfile << (*id_groups[i])[j] << " "; + for(int j=1; j<id_groups[i]->Size(); 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; i<id_groups.Size(); i++) + { + if(!id_groups[i] || id_groups[i]->Size() != 4) + continue; + + for(int j=0; j<id_groups[i]->Size(); j++) + outfile << (*id_groups[i])[j] << " "; + for(int j=1; j<id_groups[i]->Size(); 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), "<<uidpid<<":\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + + + + Array< Array<int>* > edge_to_face(numedges+1); + for(int i=0; i<edge_to_face.Size(); i++) + edge_to_face[i] = new Array<int>; + + + for(int i=0; i<idmaps.Size(); i++) + { + idmaps[i]->SetSize(numfaces); + (*idmaps[i]) = 0; + } + + + for(int i=0; i<face2edge.Size(); i++) + { + for(int j=0; j<idmaps_edge.Size(); j++) + { + int e1id,e2id,e3id; + e1id = (*idmaps_edge[j])[abs(face2edge[i][0])]; + e2id = (*idmaps_edge[j])[abs(face2edge[i][1])]; + e3id = (*idmaps_edge[j])[abs(face2edge[i][2])]; + if(e1id != 0 && e1id != abs(face2edge[i][0]) && + e2id != 0 && e2id != abs(face2edge[i][1]) && + e3id != 0 && e3id != abs(face2edge[i][2])) + { + Intersection(*edge_to_face[e1id],*edge_to_face[e2id],*edge_to_face[e3id],possible); + if(possible.Size() == 1) + { + (*idmaps[j])[possible[0]] = i+1; + (*idmaps[j])[i+1] = possible[0]; + } + else if(possible.Size() > 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<edge_to_face.Size(); i++) + delete edge_to_face[i]; + + + for(int i=0; i<idmaps_edge.Size(); i++) + delete idmaps_edge[i]; + + + id_groups.SetSize(0); + id_num.SetSize(numfaces+1); + id_num = 0; + + n2 = n4 = n8 = 0; + + for(int i=1; i<=numfaces; i++) + { + if(id_num[i] != 0) + continue; + + Array<int> group; + group.Append(i); + for(int j=0; j<idmaps.Size(); j++) + { + startsize = group.Size(); + for(int k=0; k<startsize; k++) + { + int id = (*idmaps[j])[group[k]]; + if(id != 0 && !group.Contains(id)) + { + group.Append(id); + id_num[id] = j+1+id_num[group[k]]; + } + } + } + if(group.Size() > 1) + { + id_num[i] = -1; + id_groups.Append(new Array<int>(group)); + if(group.Size() == 2) + n2++; + else + cerr << "ERROR: face identification group size = " << group.Size() << endl; + } + + } + + + for(int i=0; i<idmaps.Size(); i++) + delete idmaps[i]; + + + + + for(int i=0; i<face2edge.Size(); i++) + { + outfile << i+1 << " "; + for(int j=0; j<3; j++) + outfile << face2edge[i][j] << " "; + + if(id_num[i+1] == 0) + outfile << 0; + else if(id_num[i+1] == -1) + outfile << 1; + else + outfile << 2; + + outfile << " " << face_ids[i] <<"\n"; + } + outfile << endl; + + + outfile << "// Number of Periodic Master Faces:\n"\ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"\ + << n2 << "\n" \ + << "\n"\ + << "// MasterFaceID, SlaveFaceID, TranslCode (1=dS1 2=dS2):\n"\ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<id_groups.Size(); i++) + { + if(id_groups[i]->Size() != 2) + continue; + + for(int j=0; j<id_groups[i]->Size(); j++) + outfile << (*id_groups[i])[j] << " "; + for(int j=1; j<id_groups[i]->Size(); j++) + outfile << id_num[(*id_groups[i])[j]] << " "; + outfile << "\n"; + + delete id_groups[i]; + } + outfile << endl; + + + + + outfile << "// ElemID, FaceID0, FaceID1, FaceID2, FaceID3, "<<uidpid<<":\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + + for(ElementIndex i=0; i<mesh.GetNE(); i++) + { + if(elnum[i] >= 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<mesh.GetNE(); i++) + { + if(elnum[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<int> * > groups; + + int maxg = -1; + for(int i = 0; i<uid_to_group_3D.Size(); i++) + if(uid_to_group_3D[i] > maxg) + maxg = uid_to_group_3D[i]; + for(int i = 0; i<uid_to_group_2D.Size(); i++) + if(uid_to_group_2D[i] > maxg) + maxg = uid_to_group_2D[i]; + for(int i = 0; i<uid_to_group_1D.Size(); i++) + if(uid_to_group_1D[i] > maxg) + maxg = uid_to_group_1D[i]; + for(int i = 0; i<uid_to_group_0D.Size(); i++) + if(uid_to_group_0D[i] > maxg) + maxg = uid_to_group_0D[i]; + + groups.SetSize(maxg+1); + for(int i=0; i<groups.Size(); i++) + groups[i] = new Array<int>; + + for(ElementIndex i=0; i<mesh.GetNE(); i++) + if(uid_to_group_3D[mesh[i].GetIndex()] >= 0) + groups[uid_to_group_3D[mesh[i].GetIndex()]]->Append(i+1); + + + + + outfile << "// Object3D GroupID, #Elems <immediately followed by> ElemID List:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<numObj3D; i++) + { + outfile << i << " " << groups[i]->Size() << "\n"; + for(int j=0; j<groups[i]->Size(); j++) + outfile << (*groups[i])[j] << "\n"; + } + + for(int i=0; i<groups.Size(); i++) + groups[i]->SetSize(0); + + for(int i=0; i<face_ids.Size(); i++) + if(uid_to_group_2D[face_ids[i]] >= 0) + groups[uid_to_group_2D[face_ids[i]]]->Append(i+1); + + + outfile << "// Object2D GroupID, #Faces <immediately followed by> FaceID List:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<numObj2D; i++) + { + outfile << i << " " << groups[i]->Size() << "\n"; + for(int j=0; j<groups[i]->Size(); j++) + { + outfile << (*groups[i])[j]; + if(ports.Contains(face_ids[(*groups[i])[j]-1])) + outfile << " P"; + outfile << "\n"; + } + } + outfile << endl; + + + for(int i=0; i<groups.Size(); i++) + groups[i]->SetSize(0); + + for(int i=0; i<edge_ids.Size(); i++) + if(uid_to_group_1D[edge_ids[i]] >= 0) + groups[uid_to_group_1D[edge_ids[i]]]->Append(i+1); + + + + outfile << "// Object1D GroupID, #Edges <immediately followed by> EdgeID List:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<numObj1D; i++) + { + outfile << i << " " << groups[i]->Size() << "\n"; + for(int j=0; j<groups[i]->Size(); j++) + outfile << (*groups[i])[j] << "\n"; + } + outfile << endl; + + + for(int i=0; i<groups.Size(); i++) + groups[i]->SetSize(0); + for(PointIndex i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; 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 <immediately followed by> NodeID List:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<numObj0D; i++) + { + outfile << i << " " << groups[i]->Size() << "\n"; + for(int j=0; j<groups[i]->Size(); j++) + outfile << (*groups[i])[j] << "\n"; + } + outfile << endl; + + for(int i=0; i<groups.Size(); i++) + delete groups[i]; + + + outfile.close(); + + cout << ".tet export done" << endl; + } +} diff --git a/contrib/Netgen/libsrc/interface/writetochnog.cpp b/contrib/Netgen/libsrc/interface/writetochnog.cpp new file mode 100644 index 0000000000..c9ec6e3ce9 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writetochnog.cpp @@ -0,0 +1,108 @@ +// +// Write Tochnog file +// +// by +// +// Andreas Seltmann +// email: A.Seltmann@lsw.uni-heidelberg.de +// +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + + +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; +} + +} diff --git a/contrib/Netgen/libsrc/interface/writeuser.cpp b/contrib/Netgen/libsrc/interface/writeuser.cpp new file mode 100644 index 0000000000..6e3f918566 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writeuser.cpp @@ -0,0 +1,1026 @@ +// +// Write user dependent output file +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <geometry2d.hpp> +#include <meshing.hpp> + +namespace netgen +{ +#include "writeuser.hpp" + + + void RegisterUserFormats (Array<const char*> & names, + Array<const char*> & 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", "*", + "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 NetgenGeometry & hgeom, + const string & filename) +{ + const CSGeometry & geom = *dynamic_cast<const CSGeometry*> (&hgeom); + + 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); + + 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 CSGeometry & 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 (i = 1; i <= nseg; i++) + { + const Segment & seg = mesh.LineSegment(i); + outfile.width(4); + outfile << seg.si << " "; + + outfile << " "; + outfile.width(8); + outfile << seg[0]; + outfile << " "; + outfile.width(8); + outfile << seg[1]; + + 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; + + ofstream outfile (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; + + ofstream outfile (filename.c_str()); + + outfile.precision(10); + + int numBCs = 0; + + Array<int> faceBCs; + TABLE<int> 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<SurfaceElementIndex> 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 <sawickib@ee.pw.edu.pl> + + 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 <sawickib@ee.pw.edu.pl> + + 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 CSGeometry & 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 CSGeometry & 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<int> 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<int> edgeht(mesh.GetNP()); + + // list of edges + Array<INDEX_2> 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 +} + diff --git a/contrib/Netgen/libsrc/interface/writeuser.hpp b/contrib/Netgen/libsrc/interface/writeuser.hpp new file mode 100644 index 0000000000..e5745713cb --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writeuser.hpp @@ -0,0 +1,165 @@ +#ifndef WRITEUSER +#define WRITEUSER + +/**************************************************************************/ +/* File: writeuser.hh */ +/* Authors: many */ +/* Date: 10. Dec. 97 */ +/**************************************************************************/ + + +extern +void WriteFile (int typ, + const Mesh & mesh, + const CSGeometry & geom, + const char * filename, + const char * geomfile = NULL, + double h = 0); + + + +extern +void ReadFile (Mesh & mesh, + const string & filename); + + + + + + +extern +void WriteNeutralFormat (const Mesh & mesh, + const CSGeometry & 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 CSGeometry & geom, + const string & filename); + +extern +void WriteGmshFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename); + + +// Philippose - 29/01/2009 +// Added GMSH v2.xx Mesh Export support +void WriteGmsh2Format (const Mesh & mesh, + const CSGeometry & geom, + const string & filename); + + +// Philippose - 25/10/2009 +// Added OpenFOAM 1.5+ Mesh Export support +extern +void WriteOpenFOAM15xFormat (const Mesh & mesh, + const string & casename); + + +extern +void WriteUserChemnitz (const Mesh & mesh, + const string & filename); + +extern +void WriteJCMFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename); + + +extern +void WriteDiffPackFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename); + +extern +void WriteTochnogFormat (const Mesh & mesh, + const string & filename); + +extern +void WriteTecPlotFormat (const Mesh & mesh, + const CSGeometry & 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 CSGeometry & 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 RegisterUserFormats (Array<const char*> & names, + Array<const char*> & extensions); + + +extern bool WriteUserFormat (const string & format, + const Mesh & mesh, + const NetgenGeometry & geom, + const string & filename); + +#endif + diff --git a/contrib/Netgen/libsrc/interface/wuchemnitz.cpp b/contrib/Netgen/libsrc/interface/wuchemnitz.cpp new file mode 100644 index 0000000000..8641a8cde9 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/wuchemnitz.cpp @@ -0,0 +1,317 @@ +// Write Chemnitz file format + + +#include <mystdlib.h> + +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +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<POINT3D> points; + static Array<VOLELEMENT> volelements; + static Array<SURFELEMENT> surfelements; + + static Array<FACE> faces; + static Array<EDGE> 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<int> faceindex(volelements.Size()/5 + 1); + INDEX_2_HASHTABLE<int> 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(); + facei = faces.Append (fa); + 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(); + edgei = edges.Append (ed); + 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; + } +} diff --git a/contrib/Netgen/libsrc/linalg/Makefile.am b/contrib/Netgen/libsrc/linalg/Makefile.am new file mode 100644 index 0000000000..9503b31ed7 --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/Makefile.am @@ -0,0 +1,9 @@ +noinst_HEADERS = densemat.hpp linalg.hpp polynomial.hpp vector.hpp opti.hpp +AM_CPPFLAGS = -I$(top_srcdir)/libsrc/include +METASOURCES = AUTO +noinst_LTLIBRARIES = libla.la +libla_la_SOURCES = densemat.cpp polynomial.cpp bfgs.cpp linopt.cpp linsearch.cpp + +# vector.cpp + +libla_la_LDFLAGS = -rdynamic diff --git a/contrib/Netgen/libsrc/linalg/bfgs.cpp b/contrib/Netgen/libsrc/linalg/bfgs.cpp new file mode 100644 index 0000000000..e0f40d687e --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/bfgs.cpp @@ -0,0 +1,407 @@ +/***************************************************************************/ +/* */ +/* Vorlesung Optimierung I, Gfrerer, WS94/95 */ +/* BFGS-Verfahren zur Lösung freier nichtlinearer Optimierungsprobleme */ +/* */ +/* Programmautor: Joachim Schöberl */ +/* Matrikelnummer: 9155284 */ +/* */ +/***************************************************************************/ + +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#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 + + 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; + } + + // (*testout) << "x = " << x << ", x0 = " << x0 << endl; + return f; +} + +} diff --git a/contrib/Netgen/libsrc/linalg/densemat.cpp b/contrib/Netgen/libsrc/linalg/densemat.cpp new file mode 100644 index 0000000000..a0066e8ffd --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/densemat.cpp @@ -0,0 +1,1384 @@ +#include <mystdlib.h> + +#include <linalg.hpp> + + +namespace netgen +{ + DenseMatrix :: DenseMatrix () + { + data = NULL; + height = 0; + width = 0; + } + + DenseMatrix :: DenseMatrix (int h, int w) + { + if (!w) w = h; + width = w; + height = h; + if (h*w) + data = new double[h*w]; + else + data = 0; + + for (int i = 0 ; i < (h * w); 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<int> 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<int> & 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<int> & 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; + } + + + +} diff --git a/contrib/Netgen/libsrc/linalg/densemat.hpp b/contrib/Netgen/libsrc/linalg/densemat.hpp new file mode 100644 index 0000000000..5d721b5a98 --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/densemat.hpp @@ -0,0 +1,277 @@ +#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 <int WIDTH> +class MatrixFixWidth +{ +protected: + int height; + double * data; + +public: + /// + MatrixFixWidth () + { height = 0; data = 0; } + /// + MatrixFixWidth (int h) + { height = h; data = new double[WIDTH*height]; } + /// + ~MatrixFixWidth () + { delete [] data; } + + void SetSize (int h) + { + if (h != height) + { + delete data; + height = h; + data = new double[WIDTH*height]; + } + } + + /// + 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 <int WIDTH> +extern ostream & operator<< (ostream & ost, const MatrixFixWidth<WIDTH> & 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 diff --git a/contrib/Netgen/libsrc/linalg/linalg.hpp b/contrib/Netgen/libsrc/linalg/linalg.hpp new file mode 100644 index 0000000000..95d0c823c1 --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/linalg.hpp @@ -0,0 +1,32 @@ +#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 + + diff --git a/contrib/Netgen/libsrc/linalg/linopt.cpp b/contrib/Netgen/libsrc/linalg/linopt.cpp new file mode 100644 index 0000000000..dc5b53fa47 --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/linopt.cpp @@ -0,0 +1,73 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#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; + } + } + } +} diff --git a/contrib/Netgen/libsrc/linalg/linsearch.cpp b/contrib/Netgen/libsrc/linalg/linsearch.cpp new file mode 100644 index 0000000000..a2dd38aabf --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/linsearch.cpp @@ -0,0 +1,349 @@ +/***************************************************************************/ +/* */ +/* Problem: Liniensuche */ +/* */ +/* Programmautor: Joachim Schöberl */ +/* Matrikelnummer: 9155284 */ +/* */ +/* Algorithmus nach: */ +/* */ +/* Optimierung I, Gfrerer, WS94/95 */ +/* Algorithmus 2.1: Liniensuche Problem (ii) */ +/* */ +/***************************************************************************/ + + + +#include <mystdlib.h> + +#include <myadt.hpp> // min, max, sqr + +#include <linalg.hpp> +#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; + + while (it++ <= par.maxit_linsearch) + { + + 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; + + 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; +} +} diff --git a/contrib/Netgen/libsrc/linalg/opti.hpp b/contrib/Netgen/libsrc/linalg/opti.hpp new file mode 100644 index 0000000000..9875786900 --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/opti.hpp @@ -0,0 +1,142 @@ +#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 + diff --git a/contrib/Netgen/libsrc/linalg/polynomial.cpp b/contrib/Netgen/libsrc/linalg/polynomial.cpp new file mode 100644 index 0000000000..cc515aac0a --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/polynomial.cpp @@ -0,0 +1,198 @@ +#include <mystdlib.h> +#include <linalg.hpp> + +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; +} +} diff --git a/contrib/Netgen/libsrc/linalg/polynomial.hpp b/contrib/Netgen/libsrc/linalg/polynomial.hpp new file mode 100644 index 0000000000..3108d4dd72 --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/polynomial.hpp @@ -0,0 +1,45 @@ +#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 diff --git a/contrib/Netgen/libsrc/linalg/vector.hpp b/contrib/Netgen/libsrc/linalg/vector.hpp new file mode 100644 index 0000000000..e7c52e812b --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/vector.hpp @@ -0,0 +1,161 @@ +#ifndef FILE_VECTOR +#define FILE_VECTOR + +/* *************************************************************************/ +/* File: vector.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Oct. 94 */ +/* *************************************************************************/ + + +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); + } + + 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; } + + 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; + } + } + +}; + +template <int S> +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 + + diff --git a/contrib/Netgen/libsrc/meshing/Makefile.am b/contrib/Netgen/libsrc/meshing/Makefile.am new file mode 100644 index 0000000000..2ff94a9525 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/Makefile.am @@ -0,0 +1,31 @@ +AM_CPPFLAGS = $(MPI_INCLUDES) -I$(top_srcdir)/libsrc/include + + +noinst_HEADERS = adfront2.hpp hpref_quad.hpp meshfunc.hpp ruler3.hpp \ +adfront3.hpp findip.hpp findip2.hpp hpref_segm.hpp meshing2.hpp \ +specials.hpp bisect.hpp geomsearch.hpp hpref_tet.hpp meshing3.hpp \ +topology.hpp boundarylayer.hpp global.hpp hpref_trig.hpp meshing.hpp \ +validate.hpp classifyhpel.hpp hpref_hex.hpp improve2.hpp meshtool.hpp \ +clusters.hpp hprefinement.hpp improve3.hpp meshtype.hpp \ + hpref_prism.hpp localh.hpp msghandler.hpp curvedelems.hpp \ + hpref_pyramid.hpp meshclass.hpp ruler2.hpp bcfunctions.hpp \ + basegeom.hpp + + + +METASOURCES = AUTO + +lib_LTLIBRARIES = libmesh.la + +libmesh_la_SOURCES = 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 zrefine.cpp bcfunctions.cpp \ + parallelmesh.cpp paralleltop.cpp paralleltop.hpp basegeom.cpp diff --git a/contrib/Netgen/libsrc/meshing/adfront2.cpp b/contrib/Netgen/libsrc/meshing/adfront2.cpp new file mode 100644 index 0000000000..81bef640be --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/adfront2.cpp @@ -0,0 +1,508 @@ +/* + Advancing front class for surfaces +*/ + +#include <mystdlib.h> +#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 << "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<Point<3> > & 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 + { + pi = points.Append (FrontPoint2 (p, globind, mgi, pointonsurface)) - 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 + { + li = lines.Append(FrontLine (INDEX_2(pi1, pi2))) - 1; + } + + + if (!gi1.trignum || !gi2.trignum) + { + cout << "ERROR: 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; + } + + + /* + void AdFront2 :: IncrementClass (int li) + { + lines[li].IncrementClass(); + } + + + void AdFront2 :: ResetClass (int li) + { + lines[li].ResetClass(); + } + */ + + 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<Point3d> & locpoints, + Array<MultiPointGeomInfo> & pgeominfo, + Array<INDEX_2> & loclines, // local index + Array<INDEX> & pindex, + Array<INDEX> & 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<int, 1000> nearlines(0); + ArrayMem<int, 1000> 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<int> 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(); + loclines[i][j] = locpoints.Append (points[pi].P()); + } + 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) + { + invpindex[i] = locpoints.Append (points[i].P()); + 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); + + // 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); + } +} diff --git a/contrib/Netgen/libsrc/meshing/adfront2.hpp b/contrib/Netgen/libsrc/meshing/adfront2.hpp new file mode 100644 index 0000000000..6a8158b974 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/adfront2.hpp @@ -0,0 +1,282 @@ +#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 = -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<FrontPoint2> points; /// front points + Array<FrontLine> lines; /// front lines + + Box3d boundingbox; + Box3dTree linesearchtree; /// search tree for lines + Point3dTree pointsearchtree; /// search tree for points + Point3dTree cpointsearchtree; /// search tree for cone points (not used ???) + + Array<int> delpointl; /// list of deleted front points + Array<int> dellinel; /// list of deleted front lines + + int nfl; /// number of front lines; + INDEX_2_HASHTABLE<int> * allflines; /// all front lines ever have been + + Array<int> invpindex; + + int minval; + int starti; + +public: + /// + // AdFront2 (); + AdFront2 (const Box3d & aboundingbox); + /// + ~AdFront2 (); + + /// + // void GetPoints (Array<Point<3> > & 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<Point3d> & locpoints, + Array<MultiPointGeomInfo> & pgeominfo, + Array<INDEX_2> & loclines, // local index + Array<int> & pindex, + Array<int> & 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<int> * /* testfaces */ = NULL) const + { + return Inside (lp1) == Inside (lp2); + } + + + /// + void SetStartFront (); + /// + void PrintOpenSegments (ostream & ost) const; +}; + + + +#endif + + + diff --git a/contrib/Netgen/libsrc/meshing/adfront3.cpp b/contrib/Netgen/libsrc/meshing/adfront3.cpp new file mode 100644 index 0000000000..e8863d9f42 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/adfront3.cpp @@ -0,0 +1,868 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +/* ********************** FrontPoint ********************** */ + +namespace netgen +{ + +FrontPoint3 :: FrontPoint3 () +{ + globalindex = -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<Point<3> > & apoints) const +{ + for (PointIndex pi = PointIndex::BASE; + pi < points.Size()+PointIndex::BASE; 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.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); + + int nfn = faces.Append(FrontFace (aface)); + 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<int, PointIndex::BASE> (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 Box3dTree (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<int> & 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 (int i = PointIndex::BASE; + i < np+PointIndex::BASE; i++) + points[i].cluster = i; + + 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<PointIndex::BASE> 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<double, PointIndex::BASE> 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 (int i = PointIndex::BASE; + i < points.Size()+PointIndex::BASE; i++) + points[i].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<Point3d > & locpoints, + Array<MiniElement2d> & locfaces, // local index + Array<PointIndex> & pindex, + Array<INDEX> & findex, + INDEX_2_HASHTABLE<int> & 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; + INDEX pi; + Point3d midp, p0; + + // static Array<int, PointIndex::BASE> invpindex; + + Array<MiniElement2d> locfaces2; //all local faces in radius xh + Array<int> locfaces3; // all faces in outer radius relh + Array<INDEX> 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++) + { + 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++) + { + pi = locfaces.Get(i).PNum(j); + if (invpindex[pi] == -1) + { + pindex.Append (pi); + 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<MeshPoint> & grouppoints, + Array<MiniElement2d> & groupelements, + Array<PointIndex> & pindex, + Array<INDEX> & findex) +{ + // static Array<char> pingroup; + int i, j, changed; + + pingroup.SetSize(points.Size()); + + pingroup = 0; + for (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; + } + } + + } + while (changed); + + + // static Array<int> invpindex; + invpindex.SetSize (points.Size()); + + + for (i = 1; i <= points.Size(); i++) + if (points.Get(i).Valid()) + { + grouppoints.Append (points.Get(i).P()); + pindex.Append (i); + invpindex.Elem(i) = pindex.Size(); + } + + for (i = 1; i <= faces.Size(); i++) + if (faces.Get(i).Valid()) + { + int fused = 0; + for (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 (i = 1; i <= groupelements.Size(); i++) + for (j = 1; j <= 3; j++) + { + groupelements.Elem(i).PNum(j) = + invpindex.Get(groupelements.Elem(i).PNum(j)); + } + + /* + for (i = 1; i <= groupelements.Size(); i++) + for (j = 1; j <= 3; j++) + for (k = 1; k <= grouppoints.Size(); k++) + if (pindex.Get(k) == groupelements.Get(i).PNum(j)) + { + groupelements.Elem(i).PNum(j) = k; + break; + } + */ +} + + +void AdFront3 :: SetStartFront (int /* baseelnp */) +{ + INDEX i; + int j; + + for (i = 1; i <= faces.Size(); i++) + if (faces.Get(i).Valid()) + { + const MiniElement2d & face = faces.Get(i).Face(); + for (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<int> * 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<int, 100> 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); +} +} diff --git a/contrib/Netgen/libsrc/meshing/adfront3.hpp b/contrib/Netgen/libsrc/meshing/adfront3.hpp new file mode 100644 index 0000000000..60c6aa108a --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/adfront3.hpp @@ -0,0 +1,320 @@ +#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++; } + + /// + void RemoveFace() + { + nfacetopoint--; + if (nfacetopoint == 0) nfacetopoint = -1; + } + + /// + int 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]; + 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]; } + + void Delete () { deleted = 1; pnum[0] = pnum[1] = pnum[2] = pnum[3] = PointIndex::BASE-1; } + 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<FrontPoint3, PointIndex::BASE> points; + /// +Array<FrontFace> faces; + /// +Array<PointIndex> delpointl; + + /// which points are connected to pi ? +TABLE<int, PointIndex::BASE> * 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<int, PointIndex::BASE> invpindex; + Array<char> pingroup; + + /// +class Box3dTree * facetree; +public: + + /// + AdFront3 (); + /// + ~AdFront3 (); + /// + void GetPoints (Array<Point<3> > & 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(); } + /// + 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<int> & ifaces) const; + + /// + void GetFaceBoundingBox (int i, Box3d & box) const; + + /// + int GetLocals (int baseelement, + Array<Point3d > & locpoints, + Array<MiniElement2d> & locfaces, // local index + Array<PointIndex> & pindex, + Array<INDEX> & findex, + INDEX_2_HASHTABLE<int> & connectedpairs, + float xh, + float relh, + INDEX& facesplit); + + /// + void GetGroup (int fi, + Array<MeshPoint> & grouppoints, + Array<MiniElement2d> & groupelements, + Array<PointIndex> & pindex, + Array<INDEX> & 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<int> * testfaces = NULL) const; + + + /// + PointIndex GetGlobalIndex (PointIndex pi) const + { return points[pi].GlobalIndex(); } + /// + double Volume () const + { return vol; } + + +private: + void RebuildInternalTables(); +}; + + + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/basegeom.cpp b/contrib/Netgen/libsrc/meshing/basegeom.cpp new file mode 100644 index 0000000000..c8d642e29d --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/basegeom.cpp @@ -0,0 +1,66 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + + DLL_HEADER Array<GeometryRegister*> geometryregister; + + GeometryRegister :: ~GeometryRegister() + { ; } + + + + + + int NetgenGeometry :: GenerateMesh (Mesh*& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend) + { + if (!mesh) return 1; + + if (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 || perfstepsend <= MESHCONST_MESHVOLUME) + return 0; + + + if (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"); + } + +} diff --git a/contrib/Netgen/libsrc/meshing/basegeom.hpp b/contrib/Netgen/libsrc/meshing/basegeom.hpp new file mode 100644 index 0000000000..5f866d0738 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/basegeom.hpp @@ -0,0 +1,50 @@ +#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 (Mesh*& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend); + + virtual const Refinement & GetRefinement () const; + + 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 */) { ; } + }; + + extern DLL_HEADER Array<GeometryRegister*> geometryregister; +} + + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/bcfunctions.cpp b/contrib/Netgen/libsrc/meshing/bcfunctions.cpp new file mode 100644 index 0000000000..1bab1b75cc --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/bcfunctions.cpp @@ -0,0 +1,468 @@ + +#include <mystdlib.h> +#include <meshing.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 = DEFAULT_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<Vec3d> & 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<Vec3d> bc_colours(numentries); + Array<int> bc_num(numentries); + Array<bool> 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<Vec3d> 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<Vec3d> all_colours; + Array<int> faces_sorted; + Array<int> 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<SurfaceElementIndex> 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(); + } + } + } + } +} diff --git a/contrib/Netgen/libsrc/meshing/bcfunctions.hpp b/contrib/Netgen/libsrc/meshing/bcfunctions.hpp new file mode 100644 index 0000000000..593838afe8 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/bcfunctions.hpp @@ -0,0 +1,53 @@ +#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 void AutoColourBcProps(Mesh & mesh, const char *bccolourfile); + + extern void GetFaceColours(Mesh & mesh, Array<Vec3d> & face_colours); + + extern bool ColourMatch(Vec3d col1, Vec3d col2, double eps = 2.5e-05); +} +#endif + diff --git a/contrib/Netgen/libsrc/meshing/bisect.cpp b/contrib/Netgen/libsrc/meshing/bisect.cpp new file mode 100644 index 0000000000..afa3400dac --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/bisect.cpp @@ -0,0 +1,4071 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +#define noDEBUG + + +namespace netgen +{ + //#include "../interface/writeuser.hpp" + class MarkedTet; + class MarkedPrism; + class MarkedIdentification; + class MarkedTri; + class MarkedQuad; + + typedef MoveableArray<MarkedTet> T_MTETS; + typedef MoveableArray<MarkedPrism> T_MPRISMS; + typedef MoveableArray<MarkedIdentification> T_MIDS; + typedef MoveableArray<MarkedTri> T_MTRIS; + typedef MoveableArray<MarkedQuad> 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() + { + for (int i = 0; i < 4; i++) { faceedges[i] = 255; } + } + }; + + 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) + int np; + /// 6 or 8 point numbers + 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: + /// 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<int,PointIndex::BASE>* > & idmaps, + INDEX_2_CLOSED_HASHTABLE<int> & edgenumber) + { + PrintMessage(4,"sorting ... "); + + // if (mesh.PureTetMesh()) + if (1) + { + // new, fast version + + Array<INDEX_2> edges; + Array<int> 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<double> 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<int> eclasstab(cntedges); + for (i = 1; i <= cntedges; i++) + eclasstab.Add1 (eclasses.Get(i), i); + + + // sort edges: + Array<int> 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<int> & edgenumber, + MarkedTet & mt) + { + int i, j, k; + for (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 (i = 0; i < 3; i++) + for (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 (k = 0; k < 4; k++) + { + val = 0; + for (i = 0; i < 3; i++) + for (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<int> & edgenumber, + MarkedPrism & mp) + { + int i, j; + + if (el.GetType() == PRISM || + el.GetType() == PRISM12) + { + for (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 (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 (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 (i = 0; i < 2; i++) + for (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<int> & edgenumber, + const Array<int,PointIndex::BASE> & 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<int> & edgenumber, + MarkedTri & mt) + { + int i, j; + for (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 (i = 0; i < 2; i++) + for (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<int> & edgenumber, + MarkedQuad & mq) + { + int i; + for (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 + + int i, j, k; + + + // 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 (i = 0; i < 4; i++) + { + int cnt = 0; + for (j = 0; j < 4; j++) + if (oldtet.faceedges[j] == i) + cnt++; + if (cnt == 3) + istypep = 1; + } + + + + for (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 (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; + + j = 0; + while (j == i || j == oldtet.faceedges[i]) + j++; + 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; + j = 0; + while (j == i || j == oldtet.faceedges[i]) + j++; + 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) + { + int i; + + for (i = 0; i < 6; i++) + { + newprism1.pnums[i] = oldprism.pnums[i]; + newprism2.pnums[i] = oldprism.pnums[i]; + } + + int pe1, pe2; + pe1 = 0; + if (pe1 == oldprism.markededge) + pe1++; + 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<int> & 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 == 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) + { + int i; + + for (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, pe2; + pe1 = 0; + if (pe1 == oldtri.markededge) + pe1++; + 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) + { + int i; + + for (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<int> & cutedges) + { + int i, j; + + int hanging = 0; + for (i = 1; i <= mids.Size(); i++) + { + if (mids.Elem(i).marked) + { + hanging = 1; + continue; + } + + const int np = mids.Get(i).np; + + for(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<int> & cutedges) + { + int i,j,k; + + Array< Array<int,PointIndex::BASE>* > idmaps; + for(i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) + { + idmaps.Append(new Array<int,PointIndex::BASE>); + 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<idmaps.Size(); i++) + delete idmaps[i]; + idmaps.DeleteAll(); + } + */ + + + int MarkHangingTets (T_MTETS & mtets, + const INDEX_2_CLOSED_HASHTABLE<int> & cutedges) + { + int i, j, k; + + int hanging = 0; + for (i = 1; i <= mtets.Size(); i++) + { + MarkedTet & teti = mtets.Elem(i); + + if (teti.marked) + { + hanging = 1; + continue; + } + + for (j = 0; j < 3; j++) + for (k = j+1; k < 4; k++) + { + INDEX_2 edge(teti.pnums[j], + teti.pnums[k]); + edge.Sort(); + if (cutedges.Used (edge)) + { + teti.marked = 1; + hanging = 1; + } + } + } + + return hanging; + } + + + + int MarkHangingPrisms (T_MPRISMS & mprisms, + const INDEX_2_CLOSED_HASHTABLE<int> & cutedges) + { + int i, j, k; + + int hanging = 0; + for (i = 1; i <= mprisms.Size(); i++) + { + if (mprisms.Elem(i).marked) + { + hanging = 1; + continue; + } + + for (j = 0; j < 2; j++) + for (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; + } + + + + int MarkHangingTris (T_MTRIS & mtris, + const INDEX_2_CLOSED_HASHTABLE<int> & cutedges) + { + int i, j, k; + + int hanging = 0; + for (i = 1; i <= mtris.Size(); i++) + { + if (mtris.Get(i).marked) + { + hanging = 1; + continue; + } + for (j = 0; j < 2; j++) + for (k = j+1; k < 3; k++) + { + INDEX_2 edge(mtris.Get(i).pnums[j], + mtris.Get(i).pnums[k]); + edge.Sort(); + if (cutedges.Used (edge)) + { + mtris.Elem(i).marked = 1; + hanging = 1; + } + } + } + return hanging; + } + + + + int MarkHangingQuads (T_MQUADS & mquads, + const INDEX_2_CLOSED_HASHTABLE<int> & cutedges) + { + int i; + + int hanging = 0; + for (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<int> & conto, Array<int> & connecttonode) + { + int i, n2; + // (*testout) << "connect " << node << " to " << tonode << endl; + for (i = 1; i <= conto.EntrySize(node); i++) + { + 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<mtets.Size(); i++) + ost << mtets[i]; + + ost << mprisms.Size() << "\n"; + for(int i=0; i<mprisms.Size(); i++) + ost << mprisms[i]; + + ost << mids.Size() << "\n"; + for(int i=0; i<mids.Size(); i++) + ost << mids[i]; + + ost << mtris.Size() << "\n"; + for(int i=0; i<mtris.Size(); i++) + ost << mtris[i]; + + ost << mquads.Size() << "\n"; + for(int i=0; i<mquads.Size(); i++) + ost << mquads[i]; + ost << endl; + } + + bool ReadMarkedElements(istream & ist, const Mesh & mesh) + { + string auxstring(""); + if(ist) + ist >> 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<size; i++) + { + ist >> 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<size; i++) + ist >> mprisms[i]; + + ist >> size; + mids.SetSize(size); + for(int i=0; i<size; i++) + ist >> mids[i]; + + ist >> size; + mtris.SetSize(size); + for(int i=0; i<size; i++) + ist >> mtris[i]; + + ist >> size; + mquads.SetSize(size); + for(int i=0; i<size; i++) + ist >> mquads[i]; + + return true; + } + + + + + + void BisectTetsCopyMesh (Mesh & mesh, const class CSGeometry *, + BisectionOptions & opt, + const Array< Array<int,PointIndex::BASE>* > & idmaps, + const string & refinfofile) + { + mtets.SetName ("bisection, tets"); + mprisms.SetName ("bisection, prisms"); + mtris.SetName ("bisection, trigs"); + mquads.SetName ("bisection, quads"); + mids.SetName ("bisection, identifications"); + + //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; + */ + + 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<int> 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<int> edgenumber(np); + INDEX_2_CLOSED_HASHTABLE<int> 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; + 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 (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; j<idmaps.Size(); j++) + if(BTDefineMarkedId(el, edgenumber, *idmaps[j], mi)) + mids.Append(mi); + } + } + + + + + mesh.mlparentelement.SetSize(ne); + for (i = 1; i <= ne; i++) + mesh.mlparentelement.Elem(i) = 0; + mesh.mlparentsurfaceelement.SetSize(nse); + for (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<int,PointIndex::BASE>* > & idmaps) + { + Array< Array<MarkedTet>*,PointIndex::BASE > mtets_old(mesh.GetNP()); + Array< Array<MarkedPrism>*,PointIndex::BASE > mprisms_old(mesh.GetNP()); + Array< Array<MarkedIdentification>*,PointIndex::BASE > mids_old(mesh.GetNP()); + Array< Array<MarkedTri>*,PointIndex::BASE > mtris_old(mesh.GetNP()); + Array< Array<MarkedQuad>*,PointIndex::BASE > mquads_old(mesh.GetNP()); + + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + mtets_old[i] = new Array<MarkedTet>; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + mprisms_old[i] = new Array<MarkedPrism>; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + mids_old[i] = new Array<MarkedIdentification>; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + mtris_old[i] = new Array<MarkedTri>; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + mquads_old[i] = new Array<MarkedQuad>; + + for(int i=0; i<mtets.Size(); i++) + mtets_old[mtets[i].pnums[0]]->Append(mtets[i]); + for(int i=0; i<mprisms.Size(); i++) + mprisms_old[mprisms[i].pnums[0]]->Append(mprisms[i]); + for(int i=0; i<mids.Size(); i++) + mids_old[mids[i].pnums[0]]->Append(mids[i]); + for(int i=0; i<mtris.Size(); i++) + { + (*testout) << "i " << i << endl; + (*testout) << "mtris[i] " << mtris[i].pnums[0] << " " << mtris[i].pnums[1] << " " << mtris[i].pnums[2] << endl; + mtris_old[mtris[i].pnums[0]]->Append(mtris[i]); + } + for(int i=0; i<mquads.Size(); i++) + mquads_old[mquads[i].pnums[0]]->Append(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<int> 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<int> edgenumber(np); + INDEX_2_CLOSED_HASHTABLE<int> 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 && l<mtets_old[el[0]]->Size(); 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; j<idmaps.Size(); j++) + if(BTDefineMarkedId(el, edgenumber, *idmaps[j], mi)) + { + mids.Append(mi); + + int oldind = -1; + for(l = 0; oldind < 0 && l<mids_old[mi.pnums[0]]->Size(); 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<mesh.GetNP()+PointIndex::BASE; i++) + delete mtets_old[i]; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + delete mprisms_old[i]; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + delete mids_old[i]; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + delete mtris_old[i]; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + delete mquads_old[i]; + } +*/ + + + void UpdateEdgeMarks (Mesh & mesh, + const Array< Array<int,PointIndex::BASE>* > & idmaps) + //const Array < Array<Element>* > & elements_before, + //const Array < Array<int>* > & markedelts_num, + // const Array < Array<Element2d>* > & surfelements_before, + // const Array < Array<int>* > & 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); + + + + + mtets.SetSize(0); + mprisms.SetSize(0); + mids.SetSize(0); + mtris.SetSize(0); + mquads.SetSize(0); + + //int nv = mesh.GetNV(); + + + INDEX_2_CLOSED_HASHTABLE<int> 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; j<idmaps.Size(); j++) + if(BTDefineMarkedId(el, edgenumber, *idmaps[j], mi)) + mids.Append(mi); + + + /* + int pos = surfelements_before[el[0]]->Pos(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<oldfaces.Size(); i++) + { + delete oldfaces[i]; + delete oldmarkededges[i]; + } + */ + + } + + + + + void Refinement :: Bisect (Mesh & mesh, + BisectionOptions & opt, + Array<double> * quality_loss) const + { + PrintMessage(1,"Mesh bisection"); + PushStatus("Mesh bisection"); + + static int timer = NgProfiler::CreateTimer ("Bisect"); + NgProfiler::RegionTimer reg1 (timer); + + + + static int localizetimer = NgProfiler::CreateTimer("localize edgepoints"); + NgProfiler::RegionTimer * loct = new NgProfiler::RegionTimer(localizetimer); + LocalizeEdgePoints(mesh); + delete loct; + + Array< Array<int,PointIndex::BASE>* > idmaps; + for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) + { + if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC) + { + idmaps.Append(new Array<int,PointIndex::BASE>); + 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<int,PointIndex::BASE> v_order (mesh.GetNP()); + v_order = 0; + + for (ElementIndex ei = 0; ei < ne; ei++) + for (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 (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 (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 (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<int> cutedges(10 + 5 * (mtets.Size()+mprisms.Size()+mtris.Size()+mquads.Size())); + INDEX_2_CLOSED_HASHTABLE<int> cutedges(10 + 9 * (mtets.Size()+mprisms.Size()+mtris.Size()+mquads.Size())); + + bool noprojection = false; + + for (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(i=1; i<=mtets.Size(); i++) + mtets.Elem(i).marked = 0; + for(i=1; i<=mprisms.Size(); i++) + mprisms.Elem(i).marked = 0; + for(i=1; i<=mtris.Size(); i++) + mtris.Elem(i).marked = 0; + for(i=1; i<=mquads.Size(); i++) + mquads.Elem(i).marked = 0; + for(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.size(); ii++) + isint = (isdigit(st[ii]) != 0); + + while(inf && isint) + { + mtets.Elem(atoi(st.c_str())).marked = 3; + marked = 1; + + inf >> st; + isint = true; + for(string::size_type ii=0; isint && ii<st.size(); ii++) + isint = (isdigit(st[ii]) != 0); + } + } + else if(st == "orthobrick") + { + double bounds[6]; + for(i=0; i<6; i++) + inf >> 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(i=0; i<el.GetNP(); i++) + { + const MeshPoint & point = mesh[el[i]]; + center(0) += point(0); + center(1) += point(1); + center(2) += point(2); + } + for(i=0; i<3; i++) + center(i) *= 1./double(el.GetNP()); + if(bounds[0] <= center(0) && center(0) <= bounds[3] && + bounds[1] <= center(1) && center(1) <= bounds[4] && + bounds[2] <= center(2) && center(2) <= bounds[5]) + { + mtets[ei].marked = 3; + cnt++; + } + + +// bool contained = false; +// for(int i=0; !contained && i<el.GetNP(); i++) +// { +// const MeshPoint & point = mesh[el[i]]; +// contained = (bounds[0] <= point.X() && point.X() <= bounds[3] && +// bounds[1] <= point.Y() && point.Y() <= bounds[4] && +// bounds[2] <= point.Z() && point.Z() <= bounds[5]); +// } +// if(contained) +// { +// mtets[ei].marked = 3; +// cnt++; +// } + } + + + ostringstream strstr; + strstr.precision(2); + strstr << "marked " << float(cnt)/float(mesh.GetNE())*100. +#ifdef WIN32 + << "%%" +#else + << "%" +#endif + <<" of the elements"; + PrintMessage(4,strstr.str()); + + if(cnt > 0) + marked = 1; + + + inf >> st; + } + else + { + throw NgException("something wrong with refinementinfo file"); + } + } + } + } + else + { + inf.close(); + inf.open(opt.refinementfilename); + + char ch; + for (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 (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 (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 (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 (i = 1; i <= mtets.Size(); i++) + mtets.Elem(i).incorder = mtets.Elem(i).marked ? 1 : 0; + + for (i = 1; i <= mtets.Size(); i++) + if (mtets.Elem(i).incorder) + mtets.Elem(i).marked = 0; + + + for (i = 1; i <= mprisms.Size(); i++) + mprisms.Elem(i).incorder = mprisms.Elem(i).marked ? 1 : 0; + + for (i = 1; i <= mprisms.Size(); i++) + if (mprisms.Elem(i).incorder) + mprisms.Elem(i).marked = 0; + + + for (i = 1; i <= mtris.Size(); i++) + mtris.Elem(i).incorder = mtris.Elem(i).marked ? 1 : 0; + + for (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 (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<int> bndind(np); + bndind = 0; + for (i = 1; i <= mesh.GetNSeg(); i++) + { + const Segment & seg = mesh.LineSegment(i); + for (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 (i = 1; i <= mtets.Size(); i++) + mtets.Elem(i).incorder = 1; + for (i = 1; i <= mtets.Size(); i++) + { + if (!mtets.Elem(i).marked) + mtets.Elem(i).incorder = 0; + for (j = 0; j < 4; j++) + if (singv.Test (mtets.Elem(i).pnums[j])) + mtets.Elem(i).incorder = 0; + } + for (i = 1; i <= mtets.Size(); i++) + if (mtets.Elem(i).incorder) + mtets.Elem(i).marked = 0; + + + for (i = 1; i <= mprisms.Size(); i++) + mprisms.Elem(i).incorder = 1; + for (i = 1; i <= mprisms.Size(); i++) + { + if (!mprisms.Elem(i).marked) + mprisms.Elem(i).incorder = 0; + for (j = 0; j < 6; j++) + if (singv.Test (mprisms.Elem(i).pnums[j])) + mprisms.Elem(i).incorder = 0; + } + for (i = 1; i <= mprisms.Size(); i++) + if (mprisms.Elem(i).incorder) + mprisms.Elem(i).marked = 0; + + + for (i = 1; i <= mtris.Size(); i++) + mtris.Elem(i).incorder = 1; + for (i = 1; i <= mtris.Size(); i++) + { + if (!mtris.Elem(i).marked) + mtris.Elem(i).incorder = 0; + for (j = 0; j < 3; j++) + if (singv.Test (mtris.Elem(i).pnums[j])) + mtris.Elem(i).incorder = 0; + } + for (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 + + int nel = mtets.Size(); + for (i = 1; i <= nel; i++) + if (mtets.Elem(i).marked) + { + MarkedTet oldtet; + MarkedTet newtet1, newtet2; + int newp; + + + oldtet = mtets.Get(i); + //if(yn == "y") + // (*testout) << "bisected tet " << oldtet; + INDEX_2 edge(oldtet.pnums[oldtet.tetedge1], + oldtet.pnums[oldtet.tetedge2]); + 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); + } + + BTBisectTet (oldtet, newp, newtet1, newtet2); + + mtets.Elem(i) = newtet1; + mtets.Append (newtet2); + +#ifdef DEBUG + *testout << "tet1 has elnr = " << i << ", tet2 has elnr = " << mtets.Size() << endl; +#endif + //if(yn == "y") + // (*testout) << "and got " << newtet1 << "and " << newtet2 << endl; + + mesh.mlparentelement.Append (i); + } + + int npr = mprisms.Size(); + for (i = 1; i <= npr; i++) + if (mprisms.Elem(i).marked) + { + MarkedPrism oldprism; + MarkedPrism newprism1, newprism2; + int 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 (i = 1; i <= nid; i++) + if (mids.Elem(i).marked) + { + MarkedIdentification oldid,newid1,newid2; + Array<int> newp; + + oldid = mids.Get(i); + + Array<INDEX_2> 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 (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); + + + hangingvol = + MarkHangingTets (mtets, cutedges) + + MarkHangingPrisms (mprisms, cutedges) + + MarkHangingIdentifications (mids, cutedges); + + + int nsel = mtris.Size(); + + for (i = 1; i <= nsel; i++) + if (mtris.Elem(i).marked) + { + MarkedTri oldtri; + MarkedTri newtri1, newtri2; + PointIndex newp; + + oldtri = mtris.Get(i); + int oldpi1 = oldtri.pnums[(oldtri.markededge+1)%3]; + int oldpi2 = oldtri.pnums[(oldtri.markededge+2)%3]; + INDEX_2 edge(oldpi1, oldpi2); + edge.Sort(); + + // cerr << "edge = " << edge.I1() << "-" << edge.I2() << endl; + + 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); + } + // newp = cutedges.Get(edge); + + int si = mesh.GetFaceDescriptor (oldtri.surfid).SurfNr(); + // geom->GetSurface(si)->Project (mesh.Point(newp)); + PointGeomInfo npgi; + +// cerr << "project point " << newp << " old: " << mesh.Point(newp); + 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); +// cerr << " new: " << mesh.Point(newp) << endl; + + BTBisectTri (oldtri, newp, npgi, newtri1, newtri2); + //if(yn == "y") + // (*testout) << "bisected tri " << oldtri << "and got " << newtri1 << "and " << newtri2 << endl; + + + mtris.Elem(i) = newtri1; + mtris.Append (newtri2); + mesh.mlparentsurfaceelement.Append (i); + } + + int nquad = mquads.Size(); + for (i = 1; i <= nquad; i++) + if (mquads.Elem(i).marked) + { + MarkedQuad oldquad; + MarkedQuad newquad1, newquad2; + int 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); + } + + + hangingsurf = + MarkHangingTris (mtris, cutedges) + + MarkHangingQuads (mquads, cutedges); + + hangingedge = 0; + + int nseg = mesh.GetNSeg (); + for (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); + } + } + } + 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"); + } + + + // (*testout) << "mtets = " << mtets << endl; + + if (opt.refine_hp) + { + // + Array<int> v_order (mesh.GetNP()); + v_order = 0; + if (mesh.GetDimension() == 3) + { + for (i = 1; i <= mtets.Size(); i++) + if (mtets.Elem(i).incorder) + mtets.Elem(i).order++; + + for (i = 0; i < mtets.Size(); i++) + for (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 (i = 0; i < mtets.Size(); i++) + for (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 (i = 1; i <= mtris.Size(); i++) + if (mtris.Elem(i).incorder) + { + mtris.Elem(i).order++; + } + + for (i = 0; i < mtris.Size(); i++) + for (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 (i = 0; i < mtris.Size(); i++) + { + for (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; + } + } + } + + mtets.SetAllocSize (mtets.Size()); + mprisms.SetAllocSize (mprisms.Size()); + mids.SetAllocSize (mids.Size()); + mtris.SetAllocSize (mtris.Size()); + mquads.SetAllocSize (mquads.Size()); + + + mesh.ClearVolumeElements(); + mesh.VolumeElements().SetAllocSize (mtets.Size()+mprisms.Size()); + for (i = 1; i <= mtets.Size(); i++) + { + Element el(TET); + el.SetIndex (mtets.Get(i).matindex); + for (j = 1; j <= 4; j++) + el.PNum(j) = mtets.Get(i).pnums[j-1]; + el.SetOrder (mtets.Get(i).order); + mesh.AddVolumeElement (el); + } + for (i = 1; i <= mprisms.Size(); i++) + { + Element el(PRISM); + el.SetIndex (mprisms.Get(i).matindex); + for (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 (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 (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(); + for (i = 1; i <= mtris.Size(); i++) + { + Element2d el(TRIG); + el.SetIndex (mtris.Get(i).surfid); + el.SetOrder (mtris.Get(i).order); + for (j = 1; j <= 3; j++) + { + el.PNum(j) = mtris.Get(i).pnums[j-1]; + el.GeomInfoPi(j) = mtris.Get(i).pgeominfo[j-1]; + } + mesh.AddSurfaceElement (el); + } + for (i = 1; i <= mquads.Size(); i++) + { + Element2d el(QUAD); + el.SetIndex (mquads.Get(i).surfid); + for (j = 1; j <= 4; j++) + el.PNum(j) = mquads.Get(i).pnums[j-1]; + Swap (el.PNum(3), el.PNum(4)); + mesh.AddSurfaceElement (el); + } + + + + // write multilevel hierarchy to mesh: + np = mesh.GetNP(); + mesh.mlbetweennodes.SetSize(np); + if (mesh.mglevels <= 2) + { + PrintMessage(4,"RESETTING mlbetweennodes"); + for (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 (i = 1; i <= cutedges.Size(); i++) + if (cutedges.UsedPos(i)) + { + INDEX_2 edge; + int newpi; + cutedges.GetData (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<int> 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(); + mesh.RebuildSurfaceElementLists(); + + + // update identification tables + for (i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++) + { + Array<int,PointIndex::BASE> 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 (j = 1; j <= cutedges.Size(); j++) + if (cutedges.UsedPos(j)) + { + INDEX_2 i2; + int newpi; + cutedges.GetData (j, 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); + } + } + } + + + // 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<ElementIndex> bad_elts; + Array<double> 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<bad_elts.Size(); ii++) + strstr << "bad element " << bad_elts[ii] << "\n"; + PrintMessage(1,strstr.str()); + } + if(repaired_once || bad_elts.Size() > 0) + { + clock_t t1(clock()); + + + // update id-maps + j=0; + for(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(i=0; i<idmaps.Size(); i++) + delete idmaps[i]; + idmaps.DeleteAll(); + + mesh.UpdateTopology(); + + + + + if(refelementinfofilewrite != "") + { + PrintMessage(3,"writing marked-elements information to \"",refelementinfofilewrite,"\""); + ofstream ofst(refelementinfofilewrite.c_str()); + + WriteMarkedElements(ofst); + + ofst.close(); + } + + + mesh.CalcSurfacesOfNode(); + + PrintMessage (1, "Bisection done"); + + PopStatus(); + } + + + + + BisectionOptions :: BisectionOptions () + { + outfilename = NULL; + mlfilename = NULL; + refinementfilename = NULL; + femcode = NULL; + maxlevel = 50; + usemarkedelements = 0; + refine_hp = 0; + refine_p = 0; + } + + + Refinement :: Refinement () + { + optimizer2d = NULL; + } + + Refinement :: ~Refinement () + { + ; + } + + + void Refinement :: 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); + } + + 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; + } +} diff --git a/contrib/Netgen/libsrc/meshing/bisect.hpp b/contrib/Netgen/libsrc/meshing/bisect.hpp new file mode 100644 index 0000000000..2da9b97e8d --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/bisect.hpp @@ -0,0 +1,102 @@ +#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; + BisectionOptions (); +}; + +class ZRefinementOptions +{ +public: + int minref; + ZRefinementOptions(); +}; + + +/* +extern void BisectTets (Mesh &, const CSGeometry *, + BisectionOptions & opt); +*/ + +extern void BisectTetsCopyMesh (Mesh &, const class CSGeometry *, + BisectionOptions & opt); + +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<double> * 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, const 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<INDEX_2> & parents); + + MeshOptimize2d * Get2dOptimizer(void) const + { + return optimizer2d; + } + void Set2dOptimizer(MeshOptimize2d * opti) + { + optimizer2d = opti; + } + + + virtual void LocalizeEdgePoints(Mesh & /* mesh */) const {;} +}; + +#endif diff --git a/contrib/Netgen/libsrc/meshing/boundarylayer.cpp b/contrib/Netgen/libsrc/meshing/boundarylayer.cpp new file mode 100644 index 0000000000..94bfcbe0d0 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/boundarylayer.cpp @@ -0,0 +1,610 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + + void InsertVirtualBoundaryLayer (Mesh & mesh) + { + cout << "Insert virt. b.l." << endl; + + int surfid; + + cout << "Boundary Nr:"; + cin >> surfid; + + int i, j; + int np = mesh.GetNP(); + + cout << "Old NP: " << mesh.GetNP() << endl; + cout << "Trigs: " << mesh.GetNSE() << endl; + + BitArray bndnodes(np); + Array<int> 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 (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, 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.Point(el.PNum(Vertex_A)) - mesh.Point(el.PNum(Vertex)); + Vect_B = mesh.Point(el.PNum(Vertex_B)) - mesh.Point(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, MeshingParameters & mp) + { + int i, j; + + 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; + + cout << "Generate Prismatic Boundary Layers (Experimental)...." << endl; + + // Use an array to support creation of boundary + // layers for multiple surfaces in the future... + Array<int> surfid; + int surfinp = 0; + int prismlayers = 1; + double hfirst = 0.01; + double growthfactor = 1.0; + + // Monitor and print out the number of prism and quad elements + // added to the mesh + int numprisms = 0; + int numquads = 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(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; + + 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<MeshTopology &> (meshtopo).SetBuildEdges(true); + const_cast<MeshTopology &> (meshtopo).SetBuildFaces(true); + const_cast<MeshTopology &> (meshtopo).Update(); + + double layerht = hfirst; + + 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(); + + // Safety measure to ensure no issues with mesh + // consistency + int nseg = mesh.GetNSeg(); + + // Indicate which points need to be remapped + BitArray bndnodes(np); + + // Map of the old points to the new points + Array<int> mapto(np); + + // Growth vectors for the prismatic layer based on + // the effective surface normal at a given point + Array<Vec3d> 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 (i = 1; i <= nse; i++) + { + int snr = mesh.SurfaceElement(i).GetIndex(); + // cout << "snr = " << snr << endl; + if (surfid.Contains(snr)) + { + Element2d & sel = mesh.SurfaceElement(i); + int selNP = sel.GetNP(); + for(j = 1; j <= selNP; j++) + { + // Set the bitarray to indicate that the + // point is part of the required set + bndnodes.Set(sel.PNum(j)); + + // Vec3d& surfacenormal = Vec3d(); ???? + Vec3d surfacenormal; + + // Calculate the surface normal at the current point + // with respect to the current surface element + GetSurfaceNormal(mesh,sel,j,surfacenormal); + + // Add the surface normal to the already existent one + // (This gives the effective normal direction at corners + // and curved areas) + growthvectors.Elem(sel.PNum(j)) = growthvectors.Elem(sel.PNum(j)) + + surfacenormal; + } + } + } + + // 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 (i = 1; i <= np; i++) + { + if (bndnodes.Test(i)) + { + mapto.Elem(i) = mesh.AddPoint (mesh.Point (i)); + + growthvectors.Elem(i).Normalize(); + growthvectors.Elem(i) *= -1.0; + } + else + { + mapto.Elem(i) = 0; + growthvectors.Elem(i) = Vec3d(0,0,0); + } + } + + + // Add quad surface elements at edges for surfaces which + // dont 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; + + for (i = 1; i <= nseg; i++) + { + int seg_p1 = mesh.LineSegment(i)[0]; + int seg_p2 = mesh.LineSegment(i)[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(i) && surfid.Contains(mesh.LineSegment(i).si)) + { + // clear the bit to indicate that this segment has been processed + segsel.Clear(i); + + // Find matching segment pair on other surface + for(j = 1; j <= nseg; j++) + { + int segpair_p1 = mesh.LineSegment(j)[1]; + int segpair_p2 = mesh.LineSegment(j)[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(j) && ((segpair_p1 == seg_p1) && (segpair_p2 == seg_p2))) + { + // clear bit to indicate that processing of this segment is done + segsel.Clear(j); + + // Only worry about those surfaces which are not in the + // boundary layer list + if(!surfid.Contains(mesh.LineSegment(j).si)) + { + int pnt_commelem = 0; + int pnum_commelem = 0; + Array<int> pnt1_elems; + Array<int> pnt2_elems; + + + meshtopo.GetVertexSurfaceElements(segpair_p1,pnt1_elems); + meshtopo.GetVertexSurfaceElements(segpair_p2,pnt2_elems); + for(int k = 1; k <= pnt1_elems.Size(); k++) + { + Element2d pnt1_sel = mesh.SurfaceElement(pnt1_elems.Elem(k)); + for(int l = 1; l <= pnt2_elems.Size(); l++) + { + Element2d pnt2_sel = mesh.SurfaceElement(pnt2_elems.Elem(l)); + if((pnt1_sel.GetIndex() == mesh.LineSegment(j).si) + && (pnt2_sel.GetIndex() == mesh.LineSegment(j).si) + && (pnt1_elems.Elem(k) == pnt2_elems.Elem(l))) + { + pnt_commelem = pnt1_elems.Elem(k); + } + } + } + + 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; + + 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.LineSegment(i)[0] = mapto.Get(seg_p1); + mesh.LineSegment(i)[1] = mapto.Get(seg_p2); + mesh.LineSegment(j)[1] = mapto.Get(seg_p1); + mesh.LineSegment(j)[0] = mapto.Get(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.Get(seg_p1); + sel.PNum(3) = mapto.Get(seg_p2); + sel.PNum(2) = segpair_p2; + sel.PNum(1) = segpair_p1; + sel.SetIndex(mesh.LineSegment(j).si); + mesh.AddSurfaceElement(sel); + numquads++; + } + else + { + dbg << "\n"; + for (int k = 1; k <= pnt1_elems.Size(); k++) + { + Element2d & pnt_sel = mesh.SurfaceElement(pnt1_elems.Elem(k)); + if(pnt_sel.GetIndex() == mesh.LineSegment(j).si) + { + for(int l = 1; l <= pnt_sel.GetNP(); l++) + { + if(pnt_sel.PNum(l) == segpair_p1) + { + pnt_sel.PNum(l) = mapto.Get(seg_p1); + } + else if(pnt_sel.PNum(l) == segpair_p2) + { + pnt_sel.PNum(l) = mapto.Get(seg_p2); + } + } + } + } + + for (int k = 1; k <= pnt2_elems.Size(); k++) + { + Element2d & pnt_sel = mesh.SurfaceElement(pnt2_elems.Elem(k)); + if(pnt_sel.GetIndex() == mesh.LineSegment(j).si) + { + for(int l = 1; l <= pnt_sel.GetNP(); l++) + { + if(pnt_sel.PNum(l) == segpair_p1) + { + pnt_sel.PNum(l) = mapto.Get(seg_p1); + } + else if(pnt_sel.PNum(l) == segpair_p2) + { + pnt_sel.PNum(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.LineSegment(i)[0] = mapto.Get(seg_p1); + mesh.LineSegment(i)[1] = mapto.Get(seg_p2); + mesh.LineSegment(j)[1] = mapto.Get(seg_p1); + mesh.LineSegment(j)[0] = mapto.Get(seg_p2); + } + } + } + } + } + + // Add prismatic cells at the boundaries + cout << "Generating prism boundary layer volume elements...." << endl; + + for (i = 1; i <= nse; i++) + { + Element2d & sel = mesh.SurfaceElement(i); + if(surfid.Contains(sel.GetIndex())) + { + Element el(PRISM); + for (j = 1; j <= sel.GetNP(); j++) + { + // Check (Doublecheck) if the corresponding point has a + // copy available for remapping + if (mapto.Get(sel.PNum(j))) + { + // Define the points of the newly added Prism cell + el.PNum(j+3) = mapto.Get(sel.PNum(j)); + el.PNum(j) = sel.PNum(j); + } + } + + el.SetIndex(1); + el.Invert(); + mesh.AddVolumeElement(el); + numprisms++; + } + } + + // 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 (i = 1; i <= nse; i++) + { + Element2d & sel = mesh.SurfaceElement(i); + if(surfid.Contains(sel.GetIndex())) + { + for (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)); + } + } + } + } + + // Lock all the prism points so that the rest of the mesh can be + // optimised without invalidating the entire mesh + for (i = 1; i <= np; i++) + { + if(bndnodes.Test(i)) mesh.AddLockedPoint(i); + } + + // Now, actually pull back the old surface points to create + // the actual boundary layers + cout << "Moving and optimising boundary layer points...." << endl; + + for (i = 1; i <= np; i++) + { + Array<int> 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(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(); + } + } + + mesh.Compress(); + } + else + { + mesh.Point(i).SetPoint(pointtomove + layerht * growthvectors.Elem(i)); + } + } + } + } + + // 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(); + } + +} + diff --git a/contrib/Netgen/libsrc/meshing/boundarylayer.hpp b/contrib/Netgen/libsrc/meshing/boundarylayer.hpp new file mode 100644 index 0000000000..4bd469848f --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/boundarylayer.hpp @@ -0,0 +1,13 @@ +#ifndef FILE_BOUNDARYLAYER +#define FILE_BOUNDARYLAYER + + +/// +extern void InsertVirtualBoundaryLayer (Mesh & mesh); + +/// Create a typical prismatic boundary layer on the given +/// surfaces +extern void GenerateBoundaryLayer (Mesh & mesh, MeshingParameters & mp); + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/classifyhpel.hpp b/contrib/Netgen/libsrc/meshing/classifyhpel.hpp new file mode 100644 index 0000000000..c155537199 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/classifyhpel.hpp @@ -0,0 +1,1728 @@ +HPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & 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<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & 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<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & 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<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & 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<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & 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<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & 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<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & 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<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & 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); + +} diff --git a/contrib/Netgen/libsrc/meshing/clusters.cpp b/contrib/Netgen/libsrc/meshing/clusters.cpp new file mode 100644 index 0000000000..e89def6a85 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/clusters.cpp @@ -0,0 +1,267 @@ +#include <mystdlib.h> + +#include "meshing.hpp" + +namespace netgen +{ + + AnisotropicClusters :: AnisotropicClusters (const Mesh & amesh) + : mesh(amesh) + { + ; + } + + AnisotropicClusters :: ~AnisotropicClusters () + { + ; + } + + void AnisotropicClusters :: Update() + { + int i, j, k; + + const MeshTopology & top = mesh.GetTopology(); + + 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); + + Array<int> nnums, ednums, fanums; + int changed; + + for (i = 1; i <= cluster_reps.Size(); i++) + cluster_reps.Elem(i) = -1; + + + for (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 (j = 1; j <= elnv; j++) + nnums.Elem(j) = el.PNum(j); + for (j = 1; j <= elned; j++) + nnums.Elem(elnv+j) = nv+ednums.Elem(j); + for (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 (j = 0; j < nnums.Size(); j++) + cluster_reps.Elem(nnums[j]) = nnums[j]; + } + + + + for (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 (j = 1; j <= elnv; j++) + nnums.Elem(j) = el.PNum(j); + for (j = 1; j <= elned; j++) + nnums.Elem(elnv+j) = nv+ednums.Elem(j); + nnums.Elem(elnv+elned+1) = fanum; + + for (j = 0; j < nnums.Size(); j++) + cluster_reps.Elem(nnums[j]) = nnums[j]; + } + + 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 + { + + cnt++; + changed = 0; + + for (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 (j = 1; j <= elnv; j++) + nnums.Elem(j) = el.PNum(j); + for (j = 1; j <= elned; j++) + nnums.Elem(elnv+j) = nv+ednums.Elem(j); + for (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; + + + 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)) == + cluster_reps.Get(el.PNum(2))) + clustertab = tet_cluster12; + else if (cluster_reps.Get(el.PNum(1)) == + cluster_reps.Get(el.PNum(3))) + clustertab = tet_cluster13; + else if (cluster_reps.Get(el.PNum(1)) == + cluster_reps.Get(el.PNum(4))) + clustertab = tet_cluster14; + else if (cluster_reps.Get(el.PNum(2)) == + cluster_reps.Get(el.PNum(3))) + clustertab = tet_cluster23; + else if (cluster_reps.Get(el.PNum(2)) == + cluster_reps.Get(el.PNum(4))) + clustertab = tet_cluster24; + else if (cluster_reps.Get(el.PNum(3)) == + cluster_reps.Get(el.PNum(4))) + clustertab = tet_cluster34; + + else + clustertab = NULL; + break; + default: + clustertab = NULL; + } + + if (clustertab) + for (j = 0; j < nnums.Size(); j++) + for (k = 0; k < j; k++) + if (clustertab[j] == clustertab[k]) + { + int jj = nnums[j]; + int kk = nnums[k]; + if (cluster_reps.Get(jj) < cluster_reps.Get(kk)) + { + cluster_reps.Elem(kk) = cluster_reps.Get(jj); + changed = 1; + } + else if (cluster_reps.Get(kk) < cluster_reps.Get(jj)) + { + cluster_reps.Elem(jj) = cluster_reps.Get(kk); + 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; + } + */ + } + } + while (changed); + + /* + (*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; + } + */ + } +} diff --git a/contrib/Netgen/libsrc/meshing/clusters.hpp b/contrib/Netgen/libsrc/meshing/clusters.hpp new file mode 100644 index 0000000000..fa0de93a4a --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/clusters.hpp @@ -0,0 +1,42 @@ +#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<int> cluster_reps; + +public: + AnisotropicClusters (const Mesh & amesh); + ~AnisotropicClusters(); + + void Update(); + + 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 diff --git a/contrib/Netgen/libsrc/meshing/curvedelems.cpp b/contrib/Netgen/libsrc/meshing/curvedelems.cpp new file mode 100644 index 0000000000..df17cf1917 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/curvedelems.cpp @@ -0,0 +1,3581 @@ +#include <mystdlib.h> + +#include "meshing.hpp" + +#include "../general/autodiff.hpp" + + +namespace netgen +{ + + // bool rational = true; + + + + static void ComputeGaussRule (int n, Array<double> & xi, Array<double> & 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) + static void CalcEdgeShape (int n, double x, double * shape) + { + double 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; + } + } + + static void CalcEdgeDx (int n, double x, double * dshape) + { + double p1 = x, p2 = -1, p3 = 0; + double 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; + } + } + + static void CalcEdgeShapeDx (int n, double x, double * shape, double * dshape) + { + double p1 = x, p2 = -1, p3 = 0; + double 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 + static void CalcScaledEdgeShape (int n, double x, double t, double * 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; + } + + double p1 = x, p2 = -1, p3 = 0; + double 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 <int DIST> + static void CalcScaledEdgeShapeDxDt (int n, double x, double t, double * dshape) + { + double p1 = x, p2 = -1, p3 = 0; + double p1dx = 1, p1dt = 0; + double p2dx = 0, p2dt = 0; + double 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 <class Tx, class Tres> + 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 <class Tx, class Tt, class Tres> + 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; + } + } + } + + + + template <class S, class T> + 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 <class S, class St, class T> + 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; + } + } + + + + + + // compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1 + template <class Tx, class Ty, class Ts> + static void CalcTrigShape (int n, Tx x, Ty y, Ts * shape) + { + if (n < 3) return; + Tx hx[50], hy[50*50]; + // ScaledLegendrePolynomial (n-3, 2*x-1, 1-y, hx); + ScaledJacobiPolynomial (n-3, x, 1-y, 2, 2, hx); + + + // LegendrePolynomial (n-3, 2*y-1, hy); + for (int ix = 0; ix <= n-3; ix++) + // JacobiPolynomial (n-3, 2*y-1, 0, 0, hy+50*ix); + JacobiPolynomial (n-3, 2*y-1, 2*ix+5, 2, hy+50*ix); + + int ii = 0; + Tx bub = (1+x-y)*y*(1-x-y); + for (int iy = 0; iy <= n-3; iy++) + for (int ix = 0; ix <= n-3-iy; ix++) + shape[ii++] = bub * hx[ix]*hy[iy+50*ix]; + } + + + + static void CalcTrigShapeDxDy (int n, double x, double y, double * dshape) + { + if (n < 3) return; + + AutoDiff<2> adx(x, 0); + AutoDiff<2> ady(y, 1); + AutoDiff<2> 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); + } + + /* + if (n < 3) return; + + int ndof = (n-1)*(n-2)/2; + double h1[1000], h2[1000]; + double eps = 1e-4; + + CalcTrigShape (n, x+eps, y, h1); + CalcTrigShape (n, x-eps, y, h2); + + for (int i = 0; i < ndof; i++) + dshape[2*i] = (h1[i]-h2[i])/(2*eps); + + CalcTrigShape (n, x, y+eps, h1); + CalcTrigShape (n, x, y-eps, h2); + + for (int i = 0; i < ndof; i++) + dshape[2*i+1] = (h1[i]-h2[i])/(2*eps); + */ + } + + + + + + + + + // compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1 + template <class Tx, class Ty, class Tt, class Tr> + static void CalcScaledTrigShape (int n, Tx x, Ty y, Tt t, Tr * shape) + { + if (n < 3) return; + + Tx hx[50], hy[50*50]; + // ScaledLegendrePolynomial (n-3, (2*x-1), t-y, hx); + ScaledJacobiPolynomial (n-3, x, t-y, 2, 2, hx); + + // ScaledLegendrePolynomial (n-3, (2*y-1), t, hy); + for (int ix = 0; ix <= n-3; ix++) + ScaledJacobiPolynomial (n-3, 2*y-1, t, 2*ix+5, 2, hy+50*ix); + + + int ii = 0; + Tx bub = (t+x-y)*y*(t-x-y); + for (int iy = 0; iy <= n-3; iy++) + for (int ix = 0; ix <= n-3-iy; ix++) + shape[ii++] = bub * hx[ix]*hy[iy+50*ix]; + } + + + // compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1 + static void CalcScaledTrigShapeDxDyDt (int n, double x, double y, double t, double * dshape) + { + if (n < 3) return; + AutoDiff<3> adx(x, 0); + AutoDiff<3> ady(y, 1); + AutoDiff<3> adt(t, 2); + AutoDiff<3> 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); + } + + /* + double dshape1[6000]; + if (n < 3) return; + double hvl[1000], hvr[1000]; + int nd = (n-1)*(n-2)/2; + + double eps = 1e-6; + + CalcScaledTrigShape (n, x-eps, y, t, hvl); + CalcScaledTrigShape (n, x+eps, y, t, hvr); + for (int i = 0; i < nd; i++) + dshape[3*i] = (hvr[i]-hvl[i])/(2*eps); + + CalcScaledTrigShape (n, x, y-eps, t, hvl); + CalcScaledTrigShape (n, x, y+eps, t, hvr); + for (int i = 0; i < nd; i++) + dshape[3*i+1] = (hvr[i]-hvl[i])/(2*eps); + + CalcScaledTrigShape (n, x, y, t-eps, hvl); + CalcScaledTrigShape (n, x, y, t+eps, hvr); + for (int i = 0; i < nd; i++) + dshape[3*i+2] = (hvr[i]-hvl[i])/(2*eps); + */ + + /* + for (int i = 0; i < 3*nd; i++) + if (fabs (dshape[i]-dshape1[i]) > 1e-8 * fabs(dshape[i]) + 1e-6) + { + cerr + cerr << "big difference: " << dshape1[i] << " != " << dshape[i] << endl; + } + */ + } + + + + + + 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) + { + order = aorder; + ishighorder = 0; + + if (mesh.coarsemesh) + { + mesh.coarsemesh->GetCurvedElements().BuildCurvedElements (ref, aorder, arational); + order = aorder; + rational = arational; + ishighorder = (order > 1); + return; + } + + +#ifdef PARALLEL + if (id > 0) + { + Array<int> master_edgeorder; + Array<int> master_edgecoeffsindex; + Array<Vec<3> > master_edgecoeffs; + Array<int> master_faceorder; + Array<int> master_facecoeffsindex; + Array<Vec<3> > master_facecoeffs; + + MyMPI_Bcast (master_edgeorder, 0, mesh_comm); + MyMPI_Bcast (master_edgecoeffsindex, 0, mesh_comm); + MyMPI_Bcast (master_edgecoeffs, 0, mesh_comm); + + if (mesh.GetDimension() == 3) + { + MyMPI_Bcast (master_faceorder, 0, mesh_comm); + MyMPI_Bcast (master_facecoeffsindex, 0, mesh_comm); + MyMPI_Bcast (master_facecoeffs, 0, mesh_comm); + } + + + const MeshTopology & top = mesh.GetTopology(); + const ParallelMeshTopology & partop = mesh.GetParallelTopology (); + + edgeorder.SetSize (top.GetNEdges()); + edgecoeffsindex.SetSize (top.GetNEdges()+1); + edgecoeffsindex[0] = 0; + for (int i = 0; i < top.GetNEdges(); i++) + { + int glob = partop.GetDistantEdgeNum (0, i+1); + edgeorder[i] = master_edgeorder[glob-1]; + int ncoefs = master_edgecoeffsindex[glob]-master_edgecoeffsindex[glob-1]; + edgecoeffsindex[i+1] = edgecoeffsindex[i] + ncoefs; + } + edgecoeffs.SetSize (edgecoeffsindex[top.GetNEdges()]); + + for (int i = 0; i < top.GetNEdges(); i++) + { + int glob = partop.GetDistantEdgeNum (0, i+1); + int ncoefs = master_edgecoeffsindex[glob]-master_edgecoeffsindex[glob-1]; + for (int j = 0; j < ncoefs; j++) + edgecoeffs[edgecoeffsindex[i]+j] = master_edgecoeffs[master_edgecoeffsindex[glob-1]+j]; + } + + if (mesh.GetDimension() == 3) + { + faceorder.SetSize (top.GetNFaces()); + facecoeffsindex.SetSize (top.GetNFaces()+1); + facecoeffsindex[0] = 0; + for (int i = 0; i < top.GetNFaces(); i++) + { + int glob = partop.GetDistantFaceNum (0, i+1); + faceorder[i] = master_faceorder[glob-1]; + int ncoefs = master_facecoeffsindex[glob]-master_facecoeffsindex[glob-1]; + facecoeffsindex[i+1] = facecoeffsindex[i] + ncoefs; + } + facecoeffs.SetSize (facecoeffsindex[top.GetNFaces()]); + + for (int i = 0; i < top.GetNFaces(); i++) + { + int glob = partop.GetDistantFaceNum (0, i+1); + int ncoefs = master_facecoeffsindex[glob]-master_facecoeffsindex[glob-1]; + for (int j = 0; j < ncoefs; j++) + facecoeffs[facecoeffsindex[i]+j] = master_facecoeffs[master_facecoeffsindex[glob-1]+j]; + } + } + else + { + faceorder.SetSize (top.GetNFaces()); + faceorder = 1; + facecoeffsindex.SetSize (top.GetNFaces()+1); + facecoeffsindex = 0; + } + + ishighorder = 1; + return; + } +#endif + + + PrintMessage (1, "Curve elements, order = ", aorder); + if (rational) PrintMessage (1, "curved elements with rational splines"); + + const_cast<Mesh&> (mesh).UpdateTopology(); + const MeshTopology & top = mesh.GetTopology(); + + rational = arational; + + Array<int> edgenrs; + + edgeorder.SetSize (top.GetNEdges()); + faceorder.SetSize (top.GetNFaces()); + + edgeorder = 1; + faceorder = 1; + + if (rational) + { + edgeweight.SetSize (top.GetNEdges()); + 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 (mesh.GetDimension() == 3) + for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) + { + top.GetSurfaceElementEdges (i+1, edgenrs); + for (int j = 0; j < edgenrs.Size(); j++) + edgeorder[edgenrs[j]-1] = aorder; + faceorder[top.GetSurfaceElementFace (i+1)-1] = aorder; + } + for (SegmentIndex i = 0; i < mesh.GetNSeg(); i++) + edgeorder[top.GetSegmentEdge (i+1)-1] = aorder; + + if (rational) + { + edgeorder = 2; + faceorder = 1; + } + + + edgecoeffsindex.SetSize (top.GetNEdges()+1); + int nd = 0; + for (int i = 0; i < top.GetNEdges(); i++) + { + edgecoeffsindex[i] = nd; + nd += max (0, edgeorder[i]-1); + } + edgecoeffsindex[top.GetNEdges()] = nd; + + edgecoeffs.SetSize (nd); + edgecoeffs = Vec<3> (0,0,0); + + + facecoeffsindex.SetSize (top.GetNFaces()+1); + nd = 0; + for (int i = 0; i < top.GetNFaces(); i++) + { + facecoeffsindex[i] = nd; + if (top.GetFaceType(i+1) == TRIG) + nd += max (0, (faceorder[i]-1)*(faceorder[i]-2)/2); + else + nd += max (0, sqr(faceorder[i]-1)); + } + facecoeffsindex[top.GetNFaces()] = nd; + + facecoeffs.SetSize (nd); + facecoeffs = Vec<3> (0,0,0); + + + if (!ref || aorder <= 1) + { + order = aorder; + return; + } + + Array<double> xi, weight; + + ComputeGaussRule (aorder+4, xi, weight); // on (0,1) + + PrintMessage (3, "Curving edges"); + + if (mesh.GetDimension() == 3 || rational) + for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) + { + SetThreadPercent(double(i)/mesh.GetNSE()*100.); + const Element2d & el = mesh[i]; + top.GetSurfaceElementEdges (i+1, edgenrs); + for (int j = 0; j < edgenrs.Size(); j++) + edgenrs[j]--; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (el.GetType()); + + for (int i2 = 0; i2 < edgenrs.Size(); i2++) + { + PointIndex pi1 = edges[i2][0]-1; + PointIndex pi2 = edges[i2][1]-1; + + bool swap = el[pi1] > el[pi2]; + + Point<3> p1 = mesh[el[pi1]]; + Point<3> p2 = mesh[el[pi2]]; + + int order1 = edgeorder[edgenrs[i2]]; + int ndof = max (0, order1-1); + + if (rational && order1 >= 2) + { + Point<3> pm = Center (p1, p2); + + int surfnr = mesh.GetFaceDescriptor(el.GetIndex()).SurfNr(); + + Vec<3> n1 = ref -> GetNormal (p1, surfnr, el.GeomInfoPi(edges[i2][0])); + Vec<3> n2 = ref -> GetNormal (p2, surfnr, el.GeomInfoPi(edges[i2][1])); + + // 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[edgenrs[i2]]] = 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, el.GeomInfoPi(edges[i2][0])); + double d = Dist (pp05, p05); + + if (d < dold) + { + dold = d; + wold = w; + w += dw; + } + else + { + dw *= -0.7; + w = wold + dw; + } + } + + edgeweight[edgenrs[i2]] = 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], + mesh.GetFaceDescriptor(el.GetIndex()).SurfNr(), + el.GeomInfoPi(edges[i2][0]), + el.GeomInfoPi(edges[i2][1]), + pp, ppgi); + } + else + { + p = p2 + xi[j] * (p1-p2); + ref -> PointBetween (p2, p1, xi[j], + mesh.GetFaceDescriptor(el.GetIndex()).SurfNr(), + el.GeomInfoPi(edges[i2][1]), + el.GeomInfoPi(edges[i2][0]), + 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[edgenrs[i2]]; + for (int j = 0; j < ndof; j++) + for (int k = 0; k < 3; k++) + edgecoeffs[first+j](k) = sol(j,k); + } + } + + + + for (SegmentIndex i = 0; i < mesh.GetNSeg(); i++) + { + SetThreadPercent(double(i)/mesh.GetNSeg()*100.); + const Segment & seg = mesh[i]; + PointIndex pi1 = mesh[i][0]; + PointIndex pi2 = mesh[i][1]; + + bool swap = (pi1 > pi2); + + Point<3> p1 = mesh[pi1]; + Point<3> p2 = mesh[pi2]; + + int segnr = top.GetSegmentEdge (i+1)-1; + + int order1 = edgeorder[segnr]; + int ndof = max (0, order1-1); + + + if (rational) + { + Vec<3> tau1 = ref -> GetTangent (p1, seg.surfnr2, seg.surfnr1, seg.epgeominfo[0]); + Vec<3> tau2 = ref -> GetTangent (p2, seg.surfnr2, seg.surfnr1, seg.epgeominfo[1]); + // 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 dopt = 1e99; + // double wopt = 0; + // for (double w = 0; w <= 2; w += 0.0001) + // { + // 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, seg.surfnr1, seg.surfnr2, seg.epgeominfo[0]); + // double d = Dist (pp05, p05); + // if (d < dopt) + // { + // wopt = w; + // dopt = d; + // } + // } + + 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, seg.surfnr1, seg.surfnr2, seg.epgeominfo[0]); + 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; + + Point<3> pp; + EdgePointGeomInfo ppgi; + + if (swap) + { + p = p1 + xi[j] * (p2-p1); + ref -> PointBetween (p1, p2, xi[j], + seg.surfnr2, seg.surfnr1, + seg.epgeominfo[0], seg.epgeominfo[1], + pp, ppgi); + } + else + { + p = p2 + xi[j] * (p1-p2); + ref -> PointBetween (p2, p1, xi[j], + seg.surfnr2, seg.surfnr1, + seg.epgeominfo[1], seg.epgeominfo[0], + 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"); + + if (mesh.GetDimension() == 3) + for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) + { + SetThreadPercent(double(i)/mesh.GetNSE()*100.); + const Element2d & el = mesh[i]; + int facenr = top.GetSurfaceElementFace (i+1)-1; + + if (el.GetType() == TRIG && order >= 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]); + + int order1 = faceorder[facenr]; + int ndof = max (0, (order1-1)*(order1-2)/2); + + Vector shape(ndof); + DenseMatrix mat(ndof, ndof), inv(ndof, ndof), + rhs(ndof, 3), sol(ndof, 3); + + rhs = 0.0; + mat = 0.0; + + for (int jx = 0; jx < xi.Size(); jx++) + for (int jy = 0; jy < xi.Size(); jy++) + { + 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<2> xii (x, y); + Point<3> p1, p2; + CalcSurfaceTransformation (xii, i, p1); + p2 = p1; + ref -> ProjectToSurface (p2, mesh.GetFaceDescriptor(el.GetIndex()).SurfNr()); + + Vec<3> dist = p2-p1; + + CalcTrigShape (order1, lami[fnums[1]]-lami[fnums[0]], + 1-lami[fnums[1]]-lami[fnums[0]], &shape(0)); + + for (int k = 0; k < ndof; k++) + for (int l = 0; l < ndof; l++) + mat(k,l) += wi * shape(k) * shape(l); + + for (int k = 0; k < ndof; k++) + for (int l = 0; l < 3; l++) + rhs(k,l) += wi * shape(k) * dist(l); + } + + // *testout << "mat = " << endl << mat << endl; + // CalcInverse (mat, inv); + // Mult (inv, rhs, sol); + + for (int i = 0; i < ndof; i++) + for (int j = 0; j < 3; j++) + sol(i,j) = rhs(i,j) / mat(i,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); + } + } + + PrintMessage (3, "Complete"); + + + // compress edge and face tables + int newbase = 0; + for (int i = 0; i < edgeorder.Size(); i++) + { + bool curved = 0; + int oldbase = edgecoeffsindex[i]; + 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]; + 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; + + ishighorder = (order > 1); + // (*testout) << "edgecoeffs = " << endl << edgecoeffs << endl; + // (*testout) << "facecoeffs = " << endl << facecoeffs << endl; + + +#ifdef PARALLEL + if (ntasks > 1) + { + MyMPI_Bcast (edgeorder, 0, mesh_comm); + MyMPI_Bcast (edgecoeffsindex, 0, mesh_comm); + MyMPI_Bcast (edgecoeffs, 0, mesh_comm); + + if (mesh.GetDimension() == 3) + { + MyMPI_Bcast (faceorder, 0, mesh_comm); + MyMPI_Bcast (facecoeffsindex, 0, mesh_comm); + MyMPI_Bcast (facecoeffs, 0, mesh_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); + } + + + + + + void CurvedElements :: + CalcSegmentTransformation (double xi, SegmentIndex elnr, + Point<3> * x, Vec<3> * dxdxi, bool * curved) + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [mesh[elnr].hp_elnr]; + + // xi umrechnen + double lami[2] = { xi, 1-xi }; + double dlami[2] = { 1, -1 }; + + double coarse_xi = 0; + double 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; + } + + + Vector shapes, dshapes; + Array<Vec<3> > 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; + } + + CalcElementShapes (info, xi, shapes); + GetCoefficients (info, coefs); + + *x = 0; + for (int i = 0; i < shapes.Size(); i++) + *x += shapes(i) * coefs[i]; + + + 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; + } + + + + + void CurvedElements :: + CalcElementShapes (SegmentInfo & info, double xi, Vector & 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)); + } + } + + void CurvedElements :: + CalcElementDShapes (SegmentInfo & info, double xi, Vector & 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) + { + double 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<Vec<3> > & 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 (!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; + } + + + + Vector shapes; + MatrixFixWidth<2> dshapes; + Array<Vec<3> > coefs; + + 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; + 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; + } + } + + 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); + } + + + + + void CurvedElements :: + CalcElementShapes (SurfaceElementInfo & info, const Point<2> & xi, Vector & shapes) const + { + const Element2d & el = mesh[info.elnr]; + + shapes.SetSize(info.ndof); + // shapes = 0; + + if (rational && info.order >= 2) + { + shapes.SetSize(6); + double w = 1; + double 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++) + { + double 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::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); + + 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 + { + double x = xi(0); + double y = xi(1); + double 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; + + double 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)); + double 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; + } + + default: + throw NgException("CurvedElements::CalcShape 2d, element type not handled"); + }; + } + + + void CurvedElements :: + CalcElementDShapes (SurfaceElementInfo & info, const Point<2> & xi, MatrixFixWidth<2> & dshapes) const + { + const Element2d & el = mesh[info.elnr]; + ELEMENT_TYPE type = el.GetType(); + + double lami[4]; + + dshapes.SetSize(info.ndof); + // dshapes = 0; + + // *testout << "calcelementdshapes, info.ndof = " << info.ndof << endl; + + if (rational && info.order >= 2) + { + double w = 1; + double dw[2] = { 0, 0 }; + + + lami[0] = xi(0); lami[1] = xi(1); lami[2] = 1-xi(0)-xi(1); + double dlami[3][2] = { { 1, 0 }, { 0, 1 }, { -1, -1 }}; + double 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++) + { + double 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> 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++) + { + double ddx = dshapes(ii+j,0); + double 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> 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++) + { + double ddx = dshapes(ii+j,0); + double 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 = 0.0; + dshapes(0,0) = 1; + dshapes(1,1) = 1; + dshapes(2,0) = -1; + dshapes(2,1) = -1; + } + else + { + AutoDiff<2> x(xi(0), 0); + AutoDiff<2> y(xi(1), 1); + AutoDiff<2> lam3 = 1-x-y; + AutoDiff<2> 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; + + double shapes[4] = { + (1-xi(0))*(1-xi(1)), + xi(0) *(1-xi(1)), + xi(0) * xi(1) , + (1-xi(0))* xi(1) + }; + + double mu[4] = { + 1 - xi(0) + 1 - xi(1), + xi(0) + 1 - xi(1), + xi(0) + xi(1), + 1 - xi(0) + xi(1), + }; + + double dmu[4][2] = { + { -1, -1 }, + { 1, -1 }, + { 1, 1 }, + { -1, 1 } }; + + // double hshapes[20], hdshapes[20]; + ArrayMem<double, 20> 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]); + + double lame = shapes[vi1]+shapes[vi2]; + double 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 <int DIM_SPACE> + void CurvedElements :: + GetCoefficients (SurfaceElementInfo & info, Array<Vec<DIM_SPACE> > & coefs) const + { + const Element2d & el = mesh[info.elnr]; + coefs.SetSize (info.ndof); + // coefs = Vec<3> (0,0,0); + + for (int i = 0; i < info.nv; i++) + { + Vec<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<Vec<2> > & coefs) const; + + template void CurvedElements :: + GetCoefficients<3> (SurfaceElementInfo & info, Array<Vec<3> > & coefs) const; + + + + + + // ********************** Transform volume elements ******************* + + + bool CurvedElements :: IsElementCurved (ElementIndex elnr) const + { + 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); + } + + + + + + + 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; + } + + + Vector shapes; + MatrixFixWidth<3> dshapes; + + const Element & el = mesh[elnr]; + ELEMENT_TYPE type = el.GetType(); + + ElementInfo hinfo; + ElementInfo & info = (buffer) ? *static_cast<ElementInfo*> (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]]; + } + } + + 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; + } + + + + + void CurvedElements :: CalcElementShapes (ElementInfo & info, const Point<3> & xi, Vector & shapes) const + { + const Element & el = mesh[info.elnr]; + + if (rational && info.order >= 2) + { + shapes.SetSize(10); + double w = 1; + double 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: + { + double x = xi(0); + double y = xi(1); + double z = xi(2); + double 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: + { + double lami[6] = { xi(0), xi(1), 1-xi(0)-xi(1), xi(0), xi(1), 1-xi(0)-xi(1) }; + double 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)); + double 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); + + double bubz = lamiz[vi1]*lamiz[vi2]; + double polyz = lamiz[vi1] - lamiz[vi2]; + double 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 PYRAMID: + { + shapes = 0.0; + double x = xi(0); + double y = xi(1); + double z = xi(2); + + if (z == 1.) z = 1-1e-10; + 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; + + 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, shapes[vi1]-shapes[vi2], shapes[vi1]+shapes[vi2], &shapes(ii)); + double fac = (shapes[vi1]+shapes[vi2]) / (1-z); + for (int j = 0; j < eorder-1; j++) + shapes(ii+j) *= fac; + + ii += eorder-1; + } + } + + + + break; + } + + case HEX: + { + shapes = 0.0; + double x = xi(0); + double y = xi(1); + double 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); + break; + } + + default: + throw NgException("CurvedElements::CalcShape 3d, element type not handled"); + + }; + } + + + void CurvedElements :: + CalcElementDShapes (ElementInfo & info, const Point<3> & xi, MatrixFixWidth<3> & dshapes) const + { + const Element & el = mesh[info.elnr]; + + dshapes.SetSize(info.ndof); + dshapes = 0.0; + + + + if (rational && info.order >= 2) + { + double w = 1; + double dw[3] = { 0, 0, 0 }; + + double lami[4] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) }; + double dlami[4][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { -1, -1, -1 }}; + double 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++) + { + double 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; + } + + switch (el.GetType()) + { + case TET: + { + 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; + + double 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> 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++) + { + double ddx = dshapes(ii+j,0); + double 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> 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++) + { + double ddx = dshapes(ii+j,0); + double ddy = dshapes(ii+j,1); + double 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 (dshapes.Height() == 4) + { + dshapes = 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> x(xi(0), 0); + AutoDiff<3> y(xi(1), 1); + AutoDiff<3> z(xi(2), 2); + AutoDiff<3> lam4 = 1-x-y-z; + AutoDiff<3> 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: + { + double lami[6] = { xi(0), xi(1), 1-xi(0)-xi(1), xi(0), xi(1), 1-xi(0)-xi(1) }; + double lamiz[6] = { 1-xi(2), 1-xi(2), 1-xi(2), xi(2), xi(2), xi(2) }; + double dlamiz[6] = { -1, -1, -1, 1, 1, 1 }; + double 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; + + Vector shapei(order+1); + 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> 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++) + { + double ddx = dshapes(ii+j,0); + double 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); + } + + + + double facz = (i < 3) ? (1-xi(2)) : xi(2); + double 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; + } + } + + 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); + + double bubz = lamiz[vi1] * lamiz[vi2]; + double dbubz = dlamiz[vi1]*lamiz[vi2] + lamiz[vi1]*dlamiz[vi2]; + double polyz = lamiz[vi1] - lamiz[vi2]; + double dpolyz = dlamiz[vi1] - dlamiz[vi2]; + double bubxy = lami[(vi1)%3]; + double dbubxydx = dlami[(vi1)%3][0]; + double 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]); + + MatrixFixWidth<2> dshapei(ndf); + Vector shapei(ndf); + + 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> 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); + double ddx = dshapei(j,0); + double 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 PYRAMID: + { + dshapes = 0.0; + double x = xi(0); + double y = xi(1); + double z = xi(2); + + if (z == 1.) z = 1-1e-10; + double z1 = 1-z; + double 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; + /* old: + vdshape[0] = Vec<3>( -(z1-y)/z1, -(z1-x)/z1, ((x+y+2*z-2)*z1+(z1-y)*(z1-x))/z2 ); + vdshape[1] = Vec<3>( (z1-y)/z1, -x/z1, (-x*z1+x*(z1-y))/z2 ); + vdshape[2] = Vec<3>( y/z1, x/z1, x*y/z2 ); + vdshape[3] = Vec<3>( -y/z1, (z1-x)/z1, (-y*z1+y*(z1-x))/z2 ); + vdshape[4] = Vec<3>( 0, 0, 1 ); + */ + break; + } + + case HEX: + { + dshapes = 0.0; + + double x = xi(0); + double y = xi(1); + double 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; + + 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; + */ + } + + + + 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<double> * xi, SegmentIndex segnr, + Array<Point<3> > * x, + Array<Vec<3> > * dxdxi) + { + ; + } + + + template <int DIM_SPACE> + void CurvedElements :: + CalcMultiPointSegmentTransformation (SegmentIndex elnr, int n, + const double * xi, size_t sxi, + double * x, size_t sx, + double * dxdxi, size_t sdxdxi) + { + for (int ip = 0; ip < n; ip++) + { + Point<3> xg; + Vec<3> 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<DIM_SPACE; i++) + dxdxi[ip*sdxdxi+i] = dx(i); + } + } + + template void CurvedElements :: + CalcMultiPointSegmentTransformation<2> (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); + + + + 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); + + return; +#ifdef OLD + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [mesh[elnr].hp_elnr]; + + // xi umrechnen + double lami[4]; + FlatVector vlami(4, lami); + + ArrayMem<Point<2>, 50> coarse_xi (xi->Size()); + + for (int pi = 0; pi < xi->Size(); pi++) + { + vlami = 0; + mesh[elnr].GetShapeNew ( (*xi)[pi], vlami); + + Point<2> 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 (&coarse_xi, hpref_el.coarse_elnr, x, dxdxi); + + + Mat<2,2> trans; + Mat<3,2> dxdxic; + if (dxdxi) + { + MatrixFixWidth<2> dlami(4); + dlami = 0; + + for (int pi = 0; pi < xi->Size(); pi++) + { + mesh[elnr].GetDShapeNew ( (*xi)[pi], 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); + + dxdxic = (*dxdxi)[pi]; + (*dxdxi)[pi] = dxdxic * trans; + } + } + + return; + } + + + + + + Vector shapes; + MatrixFixWidth<2> dshapes; + Array<Vec<3> > coefs; + + + 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; + default: + cerr << "undef element in CalcMultPointSurfaceTrao" << 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]; + } + + GetCoefficients (info, coefs); + if (x) + { + for (int j = 0; j < xi->Size(); j++) + { + CalcElementShapes (info, (*xi)[j], shapes); + Point<3> val(0,0,0); + for (int i = 0; i < coefs.Size(); i++) + val += shapes(i) * coefs[i]; + (*x)[j] = val; + } + } + + if (dxdxi) + { + for (int ip = 0; ip < xi->Size(); ip++) + { + CalcElementDShapes (info, (*xi)[ip], dshapes); + + /* + (*dxdxi)[ip] = 0; + for (int i = 0; i < coefs.Size(); i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 2; k++) + (*dxdxi)[ip](j,k) += dshapes(i,k) * coefs[i](j); + */ + + Mat<3,2> ds; + ds = 0.0; + for (int i = 0; i < coefs.Size(); i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 2; k++) + ds(j,k) += dshapes(i,k) * coefs[i](j); + (*dxdxi)[ip] = ds; + } + } +#endif + } + + + + + template <int DIM_SPACE> + void CurvedElements :: + CalcMultiPointSurfaceTransformation (SurfaceElementIndex elnr, int npts, + const double * xi, size_t sxi, + double * x, size_t sx, + double * dxdxi, size_t sdxdxi) + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [mesh[elnr].hp_elnr]; + + // xi umrechnen + double lami[4]; + FlatVector vlami(4, lami); + + ArrayMem<Point<2>, 50> coarse_xi (npts); + + for (int pi = 0; pi < npts; pi++) + { + vlami = 0; + Point<2> hxi(xi[pi*sxi], xi[pi*sxi+1]); + mesh[elnr].GetShapeNew ( hxi, vlami); + + Point<2> 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<DIM_SPACE> (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) + { + MatrixFixWidth<2> dlami(4); + dlami = 0; + + for (int pi = 0; pi < npts; pi++) + { + Point<2> hxi(xi[pi*sxi], xi[pi*sxi+1]); + mesh[elnr].GetDShapeNew ( hxi, dlami); + + Mat<2,2> 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<DIM_SPACE,2> 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; + } + + Vector shapes; + MatrixFixWidth<2> dshapes; + Array<Vec<DIM_SPACE> > coefs; + + + 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; + default: + cerr << "undef element in CalcMultPointSurfaceTrao" << 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]; + } + + GetCoefficients (info, coefs); + + if (x) + { + for (int j = 0; j < npts; j++) + { + Point<2> vxi(xi[j*sxi], xi[j*sxi+1]); + CalcElementShapes (info, vxi, shapes); + + Point<DIM_SPACE> val = 0.0; + for (int i = 0; i < coefs.Size(); i++) + val += shapes(i) * coefs[i]; + + for (int k = 0; k < DIM_SPACE; k++) + x[j*sx+k] = val(k); + } + } + + if (dxdxi) + { + for (int j = 0; j < npts; j++) + { + Point<2> vxi(xi[j*sxi], xi[j*sxi+1]); + CalcElementDShapes (info, vxi, dshapes); + + Mat<DIM_SPACE,2> 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); + + + + + + + + + + + + + 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<Point<3>, 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<Vec<3> > 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 + } + + + + void CurvedElements :: + CalcMultiPointElementTransformation (ElementIndex elnr, int n, + const double * xi, size_t sxi, + double * x, size_t sx, + double * dxdxi, size_t sdxdxi) + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [mesh[elnr].hp_elnr]; + + // xi umrechnen + double lami[8]; + FlatVector vlami(8, lami); + + + ArrayMem<double, 100> coarse_xi (3*n); + + for (int pi = 0; pi < n; pi++) + { + vlami = 0; + Point<3> pxi; + for (int j = 0; j < 3; j++) + pxi(j) = xi[pi*sxi+j]; + + mesh[elnr].GetShapeNew ( pxi, 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]; + + 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> trans, dxdxic; + if (dxdxi) + { + MatrixFixWidth<3> dlami(8); + dlami = 0; + + for (int pi = 0; pi < n; pi++) + { + Point<3> 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> 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; + } + + + + + + + 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<Vec<3> > coefs(info.ndof); + GetCoefficients (info, &coefs[0]); + if (x) + { + for (int j = 0; j < n; j++) + { + Point<3> xij, xj; + for (int k = 0; k < 3; k++) + xij(k) = xi[j*sxi+k]; + + CalcElementShapes (info, xij, shapes); + xj = 0; + for (int i = 0; i < coefs.Size(); i++) + xj += shapes(i) * coefs[i]; + + for (int k = 0; k < 3; k++) + x[j*sx+k] = xj(k); + } + } + + if (dxdxi) + { + if (info.order == 1 && type == TET) + { + if (n > 0) + { + + Point<3> xij; + for (int k = 0; k < 3; k++) + xij(k) = xi[k]; + + CalcElementDShapes (info, xij, dshapes); + + Mat<3> 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> xij; + for (int k = 0; k < 3; k++) + xij(k) = xi[ip*sxi+k]; + + CalcElementDShapes (info, xij, dshapes); + + Mat<3> 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 j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + dxdxi[ip*sdxdxi+3*j+k] = dxdxij(j,k); + } + } + } + } + + + + + + + + + +}; + + diff --git a/contrib/Netgen/libsrc/meshing/curvedelems.hpp b/contrib/Netgen/libsrc/meshing/curvedelems.hpp new file mode 100644 index 0000000000..945f20c886 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/curvedelems.hpp @@ -0,0 +1,223 @@ +#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<int> edgeorder; + Array<int> faceorder; + + Array<int> edgecoeffsindex; + Array<int> facecoeffsindex; + + Array< Vec<3> > edgecoeffs; + Array< Vec<3> > facecoeffs; + + Array< double > edgeweight; // for rational 2nd order splines + + int order; + bool rational; + + bool ishighorder; + +public: + CurvedElements (const Mesh & amesh); + ~CurvedElements(); + + // bool IsHighOrder() const { return order > 1; } + bool IsHighOrder() const { return ishighorder; } + + // void SetHighOrder (int aorder) { order=aorder; } + void SetIsHighOrder (bool ho) { ishighorder = ho; } + + void BuildCurvedElements(const Refinement * ref, int aorder, bool arational = false); + + int GetOrder () { return order; } + + + bool IsSegmentCurved (SegmentIndex segnr) const; + bool IsSurfaceElementCurved (SurfaceElementIndex sei) const; + bool IsElementCurved (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<double> * xi, SegmentIndex segnr, + Array<Point<3> > * x, + Array<Vec<3> > * dxdxi); + + template <int DIM_SPACE> + void CalcMultiPointSegmentTransformation (SegmentIndex elnr, int n, + const double * xi, size_t sxi, + double * x, size_t sx, + double * dxdxi, size_t sdxdxi); + + + void CalcMultiPointSurfaceTransformation (Array< Point<2> > * xi, SurfaceElementIndex elnr, + Array< Point<3> > * x, + Array< Mat<3,2> > * dxdxi); + + template <int DIM_SPACE> + void CalcMultiPointSurfaceTransformation (SurfaceElementIndex elnr, int n, + const double * xi, size_t sxi, + double * x, size_t sx, + double * dxdxi, size_t sdxdxi); + + void CalcMultiPointElementTransformation (Array< Point<3> > * xi, ElementIndex elnr, + Array< Point<3> > * x, + Array< Mat<3,3> > * dxdxi); + + void CalcMultiPointElementTransformation (ElementIndex elnr, int n, + const double * xi, size_t sxi, + double * x, size_t sx, + double * dxdxi, size_t sdxdxi); + + + + +private: + + void CalcSegmentTransformation (double xi, SegmentIndex segnr, + Point<3> * x = NULL, Vec<3> * 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; + }; + + void CalcElementShapes (SegmentInfo & elnr, double xi, Vector & shapes) const; + void GetCoefficients (SegmentInfo & elnr, Array<Vec<3> > & coefs) const; + void CalcElementDShapes (SegmentInfo & elnr, double xi, Vector & 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 + }; + + + void CalcElementShapes (ElementInfo & info, const Point<3> & xi, Vector & shapes) const; + void GetCoefficients (ElementInfo & info, Vec<3> * coefs) const; + void CalcElementDShapes (ElementInfo & info, const Point<3> & xi, MatrixFixWidth<3> & dshapes) const; + + + class SurfaceElementInfo + { + public: + SurfaceElementIndex elnr; + int order; + int nv; + int ndof; + ArrayMem<int,4> edgenrs; + int facenr; + }; + + void CalcElementShapes (SurfaceElementInfo & elinfo, const Point<2> & xi, Vector & shapes) const; + template <int DIM_SPACE> + void GetCoefficients (SurfaceElementInfo & elinfo, Array<Vec<DIM_SPACE> > & coefs) const; + void CalcElementDShapes (SurfaceElementInfo & elinfo, const Point<2> & xi, MatrixFixWidth<2> & dshapes) const; +}; + + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/delaunay.cpp b/contrib/Netgen/libsrc/meshing/delaunay.cpp new file mode 100644 index 0000000000..90dbb62150 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/delaunay.cpp @@ -0,0 +1,1676 @@ +#include <mystdlib.h> +#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 & NB1(int i) { return nb[i-1]; } + int NB1(int i) const { return nb[i-1]; } + + 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; + } + + void GetFace1 (int i, INDEX_3 & face) const + { + face.I(1) = pnums[deltetfaces[i-1][0]]; + face.I(2) = pnums[deltetfaces[i-1][1]]; + face.I(3) = pnums[deltetfaces[i-1][2]]; + } + + void GetFace (int i, INDEX_3 & face) const + { + face.I(1) = pnums[deltetfaces[i][0]]; + face.I(2) = pnums[deltetfaces[i][1]]; + face.I(3) = pnums[deltetfaces[i][2]]; + } + + INDEX_3 GetFace1 (int i) const + { + return INDEX_3 (pnums[deltetfaces[i-1][0]], + pnums[deltetfaces[i-1][1]], + pnums[deltetfaces[i-1][2]]); + } + + INDEX_3 GetFace (int i) const + { + return INDEX_3 (pnums[deltetfaces[i][0]], + pnums[deltetfaces[i][1]], + pnums[deltetfaces[i][2]]); + } + + void GetFace1 (int i, Element2d & face) const + { + // face.SetType(TRIG); + face[0] = pnums[deltetfaces[i-1][0]]; + face[1] = pnums[deltetfaces[i-1][1]]; + face[2] = pnums[deltetfaces[i-1][2]]; + } + }; + + + + + + + + + + /* + Table to maintain neighbour elements + */ + class MeshNB + { + // face nodes -> one element + INDEX_3_CLOSED_HASHTABLE<int> faces; + + // + Array<DelaunayTet> & tets; + + public: + + // estimated number of points + MeshNB (Array<DelaunayTet> & 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).NB1(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<int> 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<int> & linked) const; + }; + + + void SphereList :: GetList (int eli, Array<int> & 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<DelaunayTet> & tempels, + Mesh & mesh, + Box3dTree & tettree, + MeshNB & meshnb, + Array<Point<3> > & centers, Array<double> & radi2, + Array<int> & connected, Array<int> & treesearch, + Array<int> & freelist, SphereList & list, + IndexSet & insphere, IndexSet & closesphere) + { + /* + find any sphere, such that newp is contained in + */ + + DelaunayTet el; + int cfelind = -1; + + const Point<3> * pp[4]; + Point<3> pc; + double r2; + Point3d tpmin, tpmax; + + tettree.GetIntersecting (newp, newp, treesearch); + + double quot,minquot(1e20); + + for (int j = 0; j < treesearch.Size(); j++) + { + int jjj = treesearch[j]; + 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; + } + } + + + /* + int i, j, k, l; + if (!felind) + { + cerr << "not in any sphere, 1" << endl; + // old, non tree search + + double mindist = 1e10; + for (j = 1; j <= tempels.Size(); j++) + { + if (tempels.Get(j).PNum(1)) + { + double toofar = + Dist2 (centers.Get(j), newp) - radi2.Get(j); + if (toofar < mindist || toofar < 1e-7) + { + mindist = toofar; + cout << " dist2 = " << Dist2 (centers.Get(j), newp) + << " radi2 = " << radi2.Get(j) << endl; + } + if (toofar < 0) + { + el = tempels.Get(j); + felind = j; + cout << "sphere found !" << endl; + break; + } + } + } + cout << "point is too far from sheres: " << mindist << endl; + } + */ + + 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 = 1; 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 + { + /* + Element2d face; + tempels.Get(helind).GetFace (k, face); + + const Point3d & p1 = mesh.Point (face.PNum(1)); + const Point3d & p2 = mesh.Point (face[1]); + const Point3d & p3 = mesh.Point (face[2]); + */ + + INDEX_3 i3 = tempels.Get(helind).GetFace (k-1); + + const Point3d & p1 = mesh.Point ( PointIndex (i3.I1())); + const Point3d & p2 = mesh.Point ( PointIndex (i3.I2())); + const Point3d & p3 = mesh.Point ( PointIndex (i3.I3())); + + + Vec3d v1(p1, p2); + Vec3d v2(p1, p3); + Vec3d n = Cross (v1, v2); + n /= n.Length(); + + if (n * Vec3d (p1, mesh.Point (tempels.Get(helind)[k-1])) > 0) + n *= -1; + + double dist = n * Vec3d (p1, newp); + + + if (dist > -1e-10) // 1e-10 + { + insphere.Add (nbind); + changed = 1; + } + + + } + } + } + } // while (changed) + + // (*testout) << "newels: " << endl; + Array<Element> newels; + + Element2d face(TRIG); + + for (int j = 1; j <= insphere.GetArray().Size(); j++) + for (int k = 1; k <= 4; k++) + { + // int elind = insphere.GetArray().Get(j); + int celind = insphere.GetArray().Get(j); + int nbind = meshnb.GetNB (celind, k); + + if (!nbind || !insphere.IsIn (nbind)) + { + tempels.Get (celind).GetFace1 (k, face); + + Element newel(TET); + 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(insphere.GetArray().Get(j))[k-1])) + > 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 (int j = 1; j <= insphere.GetArray().Size(); j++) + { + // int elind = + int celind = insphere.GetArray().Get(j); + + meshnb.Delete (celind); + list.DeleteElement (celind); + + for (int k = 0; k < 4; k++) + tempels.Elem(celind)[k] = -1; + + ((ADTree6&)tettree.Tree()).DeleteElement (celind); + freelist.Append (celind); + } + + + int hasclose = 0; + for (int j = 1; j <= closesphere.GetArray().Size(); j++) + { + int ind = closesphere.GetArray().Get(j); + if (!insphere.IsIn(ind) && + fabs (Dist2 (centers.Get (ind), newp) - radi2.Get(ind)) < 1e-8 ) + hasclose = 1; + } + + for (int j = 1; j <= newels.Size(); j++) + { + int nelind; + + if (!freelist.Size()) + { + tempels.Append (newels.Get(j)); + nelind = tempels.Size(); + } + else + { + nelind = freelist.Last(); + freelist.DeleteLast(); + + tempels.Elem(nelind) = newels.Get(j); + } + + meshnb.Add (nelind); + list.AddElement (nelind); + + for (int k = 0; k < 4; k++) + pp[k] = &mesh.Point (newels.Get(j)[k]); + + if (CalcSphereCenter (&pp[0], pc) ) + { + PrintSysError ("Delaunay: New tet is flat"); + + (*testout) << "new tet is flat" << endl; + for (int k = 1; k <= 4; k++) + (*testout) << newels.Get(j).PNum(k) << " "; + (*testout) << endl; + for (int k = 1; k <= 4; k++) + (*testout) << *pp[k-1] << " "; + (*testout) << endl; + } + + 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<DelaunayTet> & tempels, + int oldnp, DelaunayTet & startel, Point3d & pmin, Point3d & pmax) + { + int i, j, k; + const Point<3> * pp[4]; + + Array<Point<3> > centers; + Array<double> radi2; + + Point3d tpmin, tpmax; + + + // new: local box + mesh.GetBox (pmax, pmin); // lower bound for pmax, upper for pmin + for (i = 1; i <= adfront->GetNF(); i++) + { + const MiniElement2d & face = adfront->GetFace(i); + for (j = 0; j < face.GetNP(); j++) + { + pmin.SetToMin (mesh.Point (face[j])); + pmax.SetToMax (mesh.Point (face[j])); + } + } + + for (i = 0; i < mesh.LockedPoints().Size(); i++) + { + pmin.SetToMin (mesh.Point (mesh.LockedPoints()[i])); + pmax.SetToMax (mesh.Point (mesh.LockedPoints()[i])); + } + + + + Vec3d vdiag(pmin, pmax); + // double r1 = vdiag.Length(); + double r1 = sqrt (3.0) * max3(vdiag.X(), vdiag.Y(), vdiag.Z()); + vdiag = Vec3d (r1, r1, r1); + //double r2; + + Point3d pmin2 = pmin - 8 * vdiag; + Point3d pmax2 = pmax + 8 * vdiag; + + Point3d cp1(pmin2), cp2(pmax2), cp3(pmax2), cp4(pmax2); + cp2.X() = pmin2.X(); + cp3.Y() = pmin2.Y(); + cp4.Z() = pmin2.Z(); + + + + + int 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<PointIndex::BASE> usep(np); + usep.Clear(); + for (i = 1; i <= adfront->GetNF(); i++) + { + const MiniElement2d & face = adfront->GetFace(i); + for (j = 0; j < face.GetNP(); j++) + usep.Set (face[j]); + } + + for (i = oldnp + PointIndex::BASE; + i < np + PointIndex::BASE; i++) + usep.Set (i); + + for (i = 0; i < mesh.LockedPoints().Size(); i++) + usep.Set (mesh.LockedPoints()[i]); + + + Array<int> freelist; + + + int cntp = 0; + + MeshNB meshnb (tempels, mesh.GetNP() + 5); + SphereList list; + + pmin2 = pmin2 + 0.1 * (pmin2 - pmax2); + pmax2 = pmax2 + 0.1 * (pmax2 - pmin2); + + Box3dTree tettree(pmin2, pmax2); + + + tempels.Append (startel); + meshnb.Add (1); + list.AddElement (1); + Array<int> connected, treesearch; + + + tpmin = tpmax = mesh.Point(startel[0]); + for (k = 1; k < 4; k++) + { + tpmin.SetToMin (mesh.Point (startel[k])); + tpmax.SetToMax (mesh.Point (startel[k])); + } + tpmax = tpmax + 0.01 * (tpmax - tpmin); + tettree.Insert (tpmin, tpmax, 1); + + + Point<3> pc; + + for (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<int> mixed(np); + int prims[] = { 11, 13, 17, 19, 23, 29, 31, 37 }; + int prim; + + i = 0; + while (np % prims[i] == 0) i++; + prim = prims[i]; + + for (i = 1; i <= np; i++) + mixed.Elem(i) = (prim * i) % np + PointIndex::BASE; + + for (i = 1; i <= np; i++) + { + if (i % 1000 == 0) + { + if (i % 10000 == 0) + PrintDot ('+'); + else + PrintDot ('.'); + } + + multithread.percent = 100.0 * i / np; + if (multithread.terminate) + break; + + PointIndex newpi = mixed.Get(i); + + if (!usep.Test(newpi)) + continue; + + cntp++; + + const Point3d & newp = mesh.Point(newpi); + + AddDelaunayPoint (newpi, newp, tempels, mesh, + tettree, meshnb, centers, radi2, + connected, treesearch, freelist, list, insphere, closesphere); + } + + for (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) + { + int np, ne; + + PrintMessage (1, "Delaunay meshing"); + PrintMessage (3, "number of points: ", mesh.GetNP()); + PushStatus ("Delaunay meshing"); + + + Array<DelaunayTet> 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 (PointIndex pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) + tempmesh.AddPoint (mesh[pi]); + + for (int i = 1; i <= tempels.Size(); i++) + { + Element el(4); + for (int j = 0; j < 4; j++) + el[j] = tempels.Elem(i)[j]; + + el.SetIndex (1); + + 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; + 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.GetFace1 (i, self); + tempmesh.AddSurfaceElement (self); + } + + + // for (i = mesh.GetNP() - 3; i <= mesh.GetNP(); i++) + // tempmesh.AddLockedPoint (i); + for (PointIndex pi = PointIndex::BASE; + pi < tempmesh.GetNP() + PointIndex::BASE; pi++) + tempmesh.AddLockedPoint (pi); + + // tempmesh.PrintMemInfo(cout); + // tempmesh.Save ("tempmesh.vol"); + + for (int i = 1; i <= 2; 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 (int i = 1; i <= tempmesh.GetNE(); i++) + tempels.Append (tempmesh.VolumeElement(i)); + } + + + + // 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<int> openeltab(mesh.GetNOpenElements()+3); + Array<int> 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<INDEX_2> 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<int> 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<INDEX_2>::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()) + { + Box3dTree 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<int> 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<INDEX_2> innerfaces(np); + + + INDEX_3_HASHTABLE<int> 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); + } + 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; + + TABLE<int,PointIndex::BASE> elsonpoint(mesh.GetNP()); + 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.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<INDEX_2> faceht(100); + + Element2d hel(TRIG); + for (PointIndex pi = PointIndex::BASE; + pi < mesh.GetNP()+PointIndex::BASE; pi++) + { + 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.GetFace1 (j, 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).NB1(j) = i2.I1(); + tempels.Elem(i2.I1()).NB1(i2.I2()) = 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<int> 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).GetFace1(j); + /* + 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).NB1(j)) + elstack.Append (tempels.Get(ei).NB1(j)); + + /* + 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 (); + } +} diff --git a/contrib/Netgen/libsrc/meshing/delaunay2d.cpp b/contrib/Netgen/libsrc/meshing/delaunay2d.cpp new file mode 100644 index 0000000000..2b1119f190 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/delaunay2d.cpp @@ -0,0 +1,174 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +// not yet working .... + +namespace netgen +{ + + void Meshing2 :: BlockFillLocalH (Mesh & mesh, const MeshingParameters & mp) + { + double filldist = mp.filldist; + + cout << "blockfill local h" << endl; + cout << "rel filldist = " << filldist << endl; + PrintMessage (3, "blockfill local h"); + + Array<Point<3> > 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()); + + double hi = Dist (p1, p2); + if (hi > maxh) maxh = hi; + + bbox.Add (p1); + bbox.Add (p2); + } + + + cout << "bbox = " << bbox << endl; + + + // Point<3> mpc = bbox.Center(); + bbox.Increase (bbox.Diam()/2); + Box<3> meshbox = bbox; + + LocalH loch2 (bbox, 1); + + 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.5 * maxh) + { + mesh.LocalHFunction().SetH (npoints[i], maxh); + changed = true; + } + } + } + while (changed); + + 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))) + { + int 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; + } + } + + } + } + + + + // 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); + + npoints.SetSize(0); + loch2.GetOuterPoints (npoints); + + for (int i = 1; i <= npoints.Size(); i++) + { + if (meshbox.IsIn (npoints.Get(i))) + { + int gpnum = mesh.AddPoint (npoints.Get(i)); + adfront->AddPoint (npoints.Get(i), gpnum); + } + } + + } + + void Meshing2 :: Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp) + { + cout << "2D Delaunay meshing (in progress)" << endl; + + // int oldnp = mesh.GetNP(); + + cout << "np, old = " << mesh.GetNP() << endl; + + BlockFillLocalH (mesh, mp); + + + cout << "np, now = " << mesh.GetNP() << endl; + + } + +} diff --git a/contrib/Netgen/libsrc/meshing/findip.hpp b/contrib/Netgen/libsrc/meshing/findip.hpp new file mode 100644 index 0000000000..f5d8e4249f --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/findip.hpp @@ -0,0 +1,192 @@ +// find inner point + + + +inline void Minimize (const Array<Vec3d> & a, + const Array<double> & 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 <typename POINTArray, typename FACEArray> +inline int FindInnerPoint (POINTArray & points, + FACEArray & faces, + Point3d & p) +{ + static int timer = NgProfiler::CreateTimer ("FindInnerPoint"); + NgProfiler::RegionTimer reg (timer); + + Array<Vec3d> a; + Array<double> 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); +} + + + diff --git a/contrib/Netgen/libsrc/meshing/findip2.hpp b/contrib/Netgen/libsrc/meshing/findip2.hpp new file mode 100644 index 0000000000..9538553485 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/findip2.hpp @@ -0,0 +1,95 @@ +// find inner point + +template <typename POINTArray, typename FACEArray> +inline int FindInnerPoint2 (POINTArray & points, + FACEArray & faces, + Point3d & p) +{ + static int timer = NgProfiler::CreateTimer ("FindInnerPoint2"); + NgProfiler::RegionTimer reg (timer); + + Array<Vec3d> a; + Array<double> 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); +} + diff --git a/contrib/Netgen/libsrc/meshing/geomsearch.cpp b/contrib/Netgen/libsrc/meshing/geomsearch.cpp new file mode 100644 index 0000000000..dc217a4809 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/geomsearch.cpp @@ -0,0 +1,263 @@ +#include <mystdlib.h> +#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 <FrontPoint3,PointIndex::BASE> *pointsi, Array <FrontFace> *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 <int> (); + } + } + } + } + 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<MiniElement2d> & locfaces, Array<INDEX> & 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 <int> & 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; + } + */ + + } + +} diff --git a/contrib/Netgen/libsrc/meshing/geomsearch.hpp b/contrib/Netgen/libsrc/meshing/geomsearch.hpp new file mode 100644 index 0000000000..052073de59 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/geomsearch.hpp @@ -0,0 +1,117 @@ +#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 <FrontPoint3,PointIndex::BASE> *pointsi, Array <FrontFace> *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<MiniElement2d> & locfaces, Array<INDEX> & findex, + INDEX fstind, const Point3d& p0, double xh); + +private: + + Array <FrontFace> *faces; // Pointers to Arrays in Adfront + Array <FrontPoint3,PointIndex::BASE> *points; + + Array <Array <int>*> 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/Netgen/libsrc/meshing/global.cpp b/contrib/Netgen/libsrc/meshing/global.cpp new file mode 100644 index 0000000000..b0f0108a7c --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/global.cpp @@ -0,0 +1,59 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + // stringstream emptystr; + // ostream * testout = &emptystr; + // testout -> clear(ios::failbit); + + // ostream * testout = &cout; + ostream * testout = new ostream(0); + + // NetgenOutStream * testout = new NetgenOutStream; + + ostream * mycout = &cout; + ostream * myerr = &cerr; + + + // Flags parameters; + + + int silentflag = 0; + int testmode = 0; + + volatile multithreadt multithread; + + string ngdir = "."; + + Array<int> tets_in_qualclass; + + + multithreadt :: multithreadt() + { + pause =0; + testmode = 0; + redraw = 0; + drawing = 0; + terminate = 0; + running = 0; + percent = 0; + task = ""; + } + + DebugParameters debugparam; + bool verbose = 0; + + int timestamp = 0; + int GetTimeStamp() + { + return timestamp; + } + + int NextTimeStamp() + { + timestamp++; + return timestamp; + } +} diff --git a/contrib/Netgen/libsrc/meshing/global.hpp b/contrib/Netgen/libsrc/meshing/global.hpp new file mode 100644 index 0000000000..43a204930f --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/global.hpp @@ -0,0 +1,54 @@ +#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 (); + extern void ResetTime (); + + /// + extern int testmode; + + /// calling parameters + // extern Flags parameters; + + // extern DLL_HEADER MeshingParameters mparam; + + extern Array<int> tets_in_qualclass; + + class multithreadt + { + public: + int pause; + int testmode; + int redraw; + int drawing; + int terminate; + int running; + double percent; + const char * task; + bool demorunning; + multithreadt(); + }; + + extern volatile multithreadt multithread; + + extern string ngdir; + extern DebugParameters debugparam; + extern bool verbose; +} + +#endif diff --git a/contrib/Netgen/libsrc/meshing/hpref_hex.hpp b/contrib/Netgen/libsrc/meshing/hpref_hex.hpp new file mode 100644 index 0000000000..11e3f86e49 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_hex.hpp @@ -0,0 +1,236 @@ +// 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 + }; + + diff --git a/contrib/Netgen/libsrc/meshing/hpref_prism.hpp b/contrib/Netgen/libsrc/meshing/hpref_prism.hpp new file mode 100644 index 0000000000..3cceb44a57 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_prism.hpp @@ -0,0 +1,3405 @@ + + // 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 + }; + +*/ diff --git a/contrib/Netgen/libsrc/meshing/hpref_pyramid.hpp b/contrib/Netgen/libsrc/meshing/hpref_pyramid.hpp new file mode 100644 index 0000000000..521daf5081 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_pyramid.hpp @@ -0,0 +1,118 @@ + + // 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 + }; + + + + diff --git a/contrib/Netgen/libsrc/meshing/hpref_quad.hpp b/contrib/Netgen/libsrc/meshing/hpref_quad.hpp new file mode 100644 index 0000000000..2a23156d1c --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_quad.hpp @@ -0,0 +1,2082 @@ +// 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 +}; diff --git a/contrib/Netgen/libsrc/meshing/hpref_segm.hpp b/contrib/Netgen/libsrc/meshing/hpref_segm.hpp new file mode 100644 index 0000000000..2544582321 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_segm.hpp @@ -0,0 +1,122 @@ + // 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 + }; + + + + diff --git a/contrib/Netgen/libsrc/meshing/hpref_tet.hpp b/contrib/Netgen/libsrc/meshing/hpref_tet.hpp new file mode 100644 index 0000000000..df0e2af890 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_tet.hpp @@ -0,0 +1,3128 @@ + + + +// 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 +}; + diff --git a/contrib/Netgen/libsrc/meshing/hpref_trig.hpp b/contrib/Netgen/libsrc/meshing/hpref_trig.hpp new file mode 100644 index 0000000000..3676ad0f33 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_trig.hpp @@ -0,0 +1,776 @@ + + +// 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 +}; diff --git a/contrib/Netgen/libsrc/meshing/hprefinement.cpp b/contrib/Netgen/libsrc/meshing/hprefinement.cpp new file mode 100644 index 0000000000..9c8155ad55 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hprefinement.cpp @@ -0,0 +1,1969 @@ +#include <mystdlib.h> +#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: + } + } + + HPRefElement :: HPRefElement () + { + Reset(); + } + + HPRefElement :: HPRefElement(Element & el) + { + //Reset(); + np = el.GetNV(); + for (int i=0; i<np ; i++) + pnums[i] = el[i]; + + index = el.GetIndex(); + const Point3d * points = + MeshTopology :: GetVertices (el.GetType()); + for(int i=0;i<np;i++) + for(int l=0;l<3;l++) + param[i][l] = points[i].X(l+1); + type = HP_NONE; + domin=-1; domout=-1; // he: needed for segments + } + + + HPRefElement :: HPRefElement(Element2d & el) + { + //Reset(); + np = el.GetNV(); + + for (int i=0; i<np ; i++) + pnums[i] = el[i]; + + index = el.GetIndex(); + const Point3d * points = + MeshTopology :: GetVertices (el.GetType()); + for(int i=0;i<np;i++) + for(int l=0;l<3;l++) + param[i][l] = points[i].X(l+1); + type = HP_NONE; + domin=-1; domout=-1; // he: needed for segments + } + + HPRefElement :: HPRefElement(Segment & el) + { + //Reset(); + np = 2; + for (int i=0; i<np ; i++) + pnums[i] = el[i]; + const Point3d * points = + MeshTopology :: GetVertices (SEGMENT); + for(int i=0;i<np;i++) + for(int l=0;l<3;l++) + param[i][l] = points[i].X(l+1); + + /* + for (int i=0; i<np; i++) + { + param[i][0] = i; + param[i][1] = -1; param[i][2] = -1; + } + */ + + singedge_left = el.singedge_left; + singedge_right = el.singedge_right; + type = HP_NONE; + // he: needed for orientation! + domin = el.domin; + domout = el.domout; + } + + HPRefElement :: HPRefElement(HPRefElement & el) + { + //Reset(); + np = el.np; + for (int i=0; i<np ; i++) + { + pnums[i] = el[i]; + for(int l=0; l<3; l++) param[i][l] = el.param[i][l]; + } + 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_right; + domin = el.domin; // he: needed for segments + domout=el.domout; + + } + + void HPRefElement :: SetType (HPREF_ELEMENT_TYPE t) + { + type = t; + switch(type) + { + case HP_SEGM: np=2; break; + case HP_TRIG: np=3; break; + case HP_QUAD: np=4; break; + case HP_TET: np=4; break; + case HP_PRISM: np=6; break; + case HP_PYRAMID: np=5; break; + case HP_HEX: np=8; break; + + default: + cerr << "HPRefElement: illegal type " << type << endl; + throw NgException ("HPRefElement::SetType: illegal type"); + } + + for(int k = 0; k < 8;k++) + { + pnums[k]=0; + for(int l = 0; l < 3; l++) + param[k][l]=0.; + } + } + + + HPRef_Struct * Get_HPRef_Struct (HPREF_ELEMENT_TYPE type) + { + HPRef_Struct * hps = NULL; + + switch (type) + { + case HP_SEGM: + hps = &refsegm; break; + case HP_SEGM_SINGCORNERL: + hps = &refsegm_scl; break; + case HP_SEGM_SINGCORNERR: + hps = &refsegm_scr; break; + case HP_SEGM_SINGCORNERS: + hps = &refsegm_sc2; break; + + case HP_TRIG: + hps = &reftrig; break; + case HP_TRIG_SINGCORNER: + hps = &reftrig_singcorner; break; + case HP_TRIG_SINGCORNER12: + hps = &reftrig_singcorner12; break; + case HP_TRIG_SINGCORNER123: + hps = &reftrig_singcorner123; break; + case HP_TRIG_SINGCORNER123_2D: + hps = &reftrig_singcorner123_2D; break; + case HP_TRIG_SINGEDGE: + hps = &reftrig_singedge; break; + case HP_TRIG_SINGEDGECORNER1: + hps = &reftrig_singedgecorner1; break; + case HP_TRIG_SINGEDGECORNER2: + hps = &reftrig_singedgecorner2; break; + case HP_TRIG_SINGEDGECORNER12: + hps = &reftrig_singedgecorner12; break; + case HP_TRIG_SINGEDGECORNER3: + hps = &reftrig_singedgecorner3; break; + case HP_TRIG_SINGEDGECORNER13: + hps = &reftrig_singedgecorner13; break; + case HP_TRIG_SINGEDGECORNER23: + hps = &reftrig_singedgecorner23; break; + case HP_TRIG_SINGEDGECORNER123: + hps = &reftrig_singedgecorner123; break; + case HP_TRIG_SINGEDGES: + hps = &reftrig_singedges; break; + case HP_TRIG_SINGEDGES2: + hps = &reftrig_singedges2; break; + case HP_TRIG_SINGEDGES3: + hps = &reftrig_singedges3; break; + case HP_TRIG_SINGEDGES23: + hps = &reftrig_singedges23; break; + case HP_TRIG_3SINGEDGES: + hps = &reftrig_3singedges; break; + + + case HP_QUAD: + hps = &refquad; break; + case HP_DUMMY_QUAD_SINGCORNER: + hps = &refdummyquad_singcorner; break; + case HP_QUAD_SINGCORNER: + hps = &refquad_singcorner; break; + case HP_QUAD_SINGEDGE: + hps = &refquad_singedge; break; + + case HP_QUAD_0E_2VA: + hps = &refquad_0e_2va; break; + case HP_QUAD_0E_2VB: + hps = &refquad_0e_2vb; break; + + case HP_QUAD_0E_3V: + hps = &refquad_0e_3v; break; + case HP_QUAD_0E_4V: + hps = &refquad_0e_4v; break; + + case HP_QUAD_1E_1VA: + hps = &refquad_1e_1va; break; + case HP_QUAD_1E_1VB: + hps = &refquad_1e_1vb; break; + case HP_QUAD_1E_1VC: + hps = &refquad_1e_1vc; break; + case HP_QUAD_1E_1VD: + hps = &refquad_1e_1vd; break; + + case HP_QUAD_1E_2VA: + hps = &refquad_1e_2va; break; + case HP_QUAD_1E_2VB: + hps = &refquad_1e_2vb; break; + case HP_QUAD_1E_2VC: + hps = &refquad_1e_2vc; break; + case HP_QUAD_1E_2VD: + hps = &refquad_1e_2vd; break; + case HP_QUAD_1E_2VE: + hps = &refquad_1e_2ve; break; + case HP_QUAD_1E_2VF: + hps = &refquad_1e_2vf; break; + + case HP_QUAD_1E_3VA: + hps = &refquad_1e_3va; break; + case HP_QUAD_1E_3VB: + hps = &refquad_1e_3vb; break; + case HP_QUAD_1E_3VC: + hps = &refquad_1e_3vc; break; + case HP_QUAD_1E_3VD: + hps = &refquad_1e_3vd; break; + case HP_QUAD_1E_4V: + hps = &refquad_1e_4v; break; + + + case HP_QUAD_2E: + hps = &refquad_2e; break; + case HP_QUAD_2E_1VA: + hps = &refquad_2e_1va; break; + case HP_QUAD_2E_1VB: + hps = &refquad_2e_1vb; break; + case HP_QUAD_2E_1VC: + hps = &refquad_2e_1vc; break; + case HP_QUAD_2E_2VA: + hps = &refquad_2e_2va; break; + case HP_QUAD_2E_2VB: + hps = &refquad_2e_2vb; break; + case HP_QUAD_2E_2VC: + hps = &refquad_2e_2vc; break; + case HP_QUAD_2E_3V: + hps = &refquad_2e_3v; break; + + case HP_QUAD_2EB_0V: + hps = &refquad_2eb_0v; break; + + case HP_QUAD_2EB_1VA: + hps = &refquad_2eb_1va; break; + case HP_QUAD_2EB_1VB: + hps = &refquad_2eb_1vb; break; + + + case HP_QUAD_2EB_2VA: + hps = &refquad_2eb_2va; break; + case HP_QUAD_2EB_2VB: + hps = &refquad_2eb_2vb; break; + case HP_QUAD_2EB_2VC: + hps = &refquad_2eb_2vc; break; + case HP_QUAD_2EB_2VD: + hps = &refquad_2eb_2vd; break; + + case HP_QUAD_2EB_3VA: + hps = &refquad_2eb_3va; break; + case HP_QUAD_2EB_3VB: + hps = &refquad_2eb_3vb; break; + + case HP_QUAD_2EB_4V: + hps = &refquad_2eb_4v; break; + + case HP_QUAD_3E: + hps = &refquad_3e; break; + case HP_QUAD_3E_3VA: + hps = &refquad_3e_3va; break; + case HP_QUAD_3E_3VB: + hps = &refquad_3e_3vb; break; + case HP_QUAD_3E_4V: + hps = &refquad_3e_4v; break; + + + case HP_QUAD_4E: + hps = &refquad_4e; break; + + + case HP_TET: + hps = &reftet; break; + case HP_TET_0E_1V: + hps = &reftet_0e_1v; break; + case HP_TET_0E_2V: + hps = &reftet_0e_2v; break; + case HP_TET_0E_3V: + hps = &reftet_0e_3v; break; + case HP_TET_0E_4V: + hps = &reftet_0e_4v; break; + + case HP_TET_1E_0V: + hps = &reftet_1e_0v; break; + case HP_TET_1E_1VA: + hps = &reftet_1e_1va; break; + case HP_TET_1E_1VB: + hps = &reftet_1e_1vb; break; + + case HP_TET_1E_2VA: + hps = &reftet_1e_2va; break; + case HP_TET_1E_2VB: + hps = &reftet_1e_2vb; break; + case HP_TET_1E_2VC: + hps = &reftet_1e_2vc; break; + case HP_TET_1E_2VD: + hps = &reftet_1e_2vd; break; + + case HP_TET_1E_3VA: + hps = &reftet_1e_3va; break; + case HP_TET_1E_3VB: + hps = &reftet_1e_3vb; break; + case HP_TET_1E_4V: + hps = &reftet_1e_4v; break; + + case HP_TET_2EA_0V: + hps = &reftet_2ea_0v; break; + case HP_TET_2EA_1VB: + hps = &reftet_2ea_1vb; break; + case HP_TET_2EA_1VC: + hps = &reftet_2ea_1vc; break; + case HP_TET_2EA_1VA: + hps = &reftet_2ea_1va; break; + case HP_TET_2EA_2VA: + hps = &reftet_2ea_2va; break; + case HP_TET_2EA_2VB: + hps = &reftet_2ea_2vb; break; + case HP_TET_2EA_2VC: + hps = &reftet_2ea_2vc; break; + case HP_TET_2EA_3V: + hps = &reftet_2ea_3v; break; + + case HP_TET_2EB_0V: + hps = &reftet_2eb_0v; break; + case HP_TET_2EB_1V: + hps = &reftet_2eb_1v; break; + case HP_TET_2EB_2VA: + hps = &reftet_2eb_2va; break; + case HP_TET_2EB_2VB: + hps = &reftet_2eb_2vb; break; + case HP_TET_2EB_2VC: + hps = &reftet_2eb_2vc; break; + case HP_TET_2EB_3V: + hps = &reftet_2eb_3v; break; + case HP_TET_2EB_4V: + hps = &reftet_2eb_4v; break; + + + case HP_TET_3EA_0V: + hps = &reftet_3ea_0v; break; + case HP_TET_3EA_1V: + hps = &reftet_3ea_1v; break; + case HP_TET_3EA_2V: + hps = &reftet_3ea_2v; break; + case HP_TET_3EA_3V: + hps = &reftet_3ea_3v; break; + + case HP_TET_3EB_0V: + hps = &reftet_3eb_0v; break; + case HP_TET_3EB_1V: + hps = &reftet_3eb_1v; break; + case HP_TET_3EB_2V: + hps = &reftet_3eb_2v; break; + case HP_TET_3EC_0V: + hps = &reftet_3ec_0v; break; + case HP_TET_3EC_1V: + hps = &reftet_3ec_1v; break; + case HP_TET_3EC_2V: + hps = &reftet_3ec_2v; break; + + + case HP_TET_1F_0E_0V: + hps = &reftet_1f_0e_0v; break; + case HP_TET_1F_0E_1VA: + hps = &reftet_1f_0e_1va; break; + case HP_TET_1F_0E_1VB: + hps = &reftet_1f_0e_1vb; break; + case HP_TET_1F_1EA_0V: + hps = &reftet_1f_1ea_0v; break; + case HP_TET_1F_1EB_0V: + hps = &reftet_1f_1eb_0v; break; + case HP_TET_2F_0E_0V: + hps = &reftet_2f_0e_0v; break; + + + case HP_PRISM: + hps = &refprism; break; + case HP_PRISM_SINGEDGE: + hps = &refprism_singedge; break; + // case HP_PRISM_SINGEDGE_H1: + // hps = &refprism_singedge_h1; break; + // case HP_PRISM_SINGEDGE_H12: + // hps = &refprism_singedge_h12; break; + case HP_PRISM_SINGEDGE_V12: + hps = &refprism_singedge_v12; break; + + + case HP_PRISM_1FA_0E_0V: + hps = &refprism_1fa_0e_0v; break; + case HP_PRISM_2FA_0E_0V: + hps = &refprism_2fa_0e_0v; break; + case HP_PRISM_1FB_0E_0V: + hps = &refprism_1fb_0e_0v; break; + case HP_PRISM_1FB_1EA_0V: + hps = &refprism_1fb_1ea_0v; break; + + case HP_PRISM_1FA_1E_0V: + hps = &refprism_1fa_1e_0v; break; + case HP_PRISM_2FA_1E_0V: + hps = &refprism_2fa_1e_0v; break; + case HP_PRISM_1FA_1FB_0E_0V: + hps = &refprism_1fa_1fb_0e_0v; break; + case HP_PRISM_2FA_1FB_0E_0V: + hps = &refprism_2fa_1fb_0e_0v; break; + case HP_PRISM_1FA_1FB_1EA_0V: + hps = &refprism_1fa_1fb_1ea_0v; break; + case HP_PRISM_1FA_1FB_1EB_0V: + hps = &refprism_1fa_1fb_1eb_0v; break; + case HP_PRISM_2FA_1FB_1EA_0V: + hps = &refprism_2fa_1fb_1ea_0v; break; + case HP_PRISM_1FB_1EC_0V: + hps = &refprism_1fb_1ec_0v; break; + case HP_PRISM_1FA_1FB_1EC_0V: + hps = &refprism_1fa_1fb_1ec_0v; break; + case HP_PRISM_2FA_1FB_1EC_0V: + hps = &refprism_2fa_1fb_1ec_0v; break; + case HP_PRISM_1FB_2EA_0V: + hps = &refprism_1fb_2ea_0v; break; + case HP_PRISM_1FA_1FB_2EA_0V: + hps = &refprism_1fa_1fb_2ea_0v; break; + case HP_PRISM_2FA_1FB_2EA_0V: + hps = &refprism_2fa_1fb_2ea_0v; break; + case HP_PRISM_1FB_2EB_0V: + hps = &refprism_1fb_2eb_0v; break; + case HP_PRISM_1FA_1FB_2EB_0V: + hps = &refprism_1fa_1fb_2eb_0v; break; + case HP_PRISM_1FA_1FB_2EC_0V: + hps = &refprism_1fa_1fb_2ec_0v; break; + case HP_PRISM_2FA_1FB_2EB_0V: + hps = &refprism_2fa_1fb_2eb_0v; break; + case HP_PRISM_1FB_3E_0V: + hps = &refprism_1fb_3e_0v; break; + case HP_PRISM_1FA_1FB_3E_0V: + hps = &refprism_1fa_1fb_3e_0v; break; + case HP_PRISM_2FA_1FB_3E_0V: + hps = &refprism_2fa_1fb_3e_0v; break; + case HP_PRISM_2FB_0E_0V: + hps = &refprism_2fb_0e_0v; break; + case HP_PRISM_1FA_2FB_0E_0V: + hps = &refprism_1fa_2fb_0e_0v; break; + case HP_PRISM_2FA_2FB_0E_0V: + hps = &refprism_2fa_2fb_0e_0v; break; + case HP_PRISM_2FB_1EC_0V: + hps = &refprism_2fb_1ec_0v; break; + case HP_PRISM_1FA_2FB_1EC_0V: + hps = &refprism_1fa_2fb_1ec_0v; break; + case HP_PRISM_2FA_2FB_1EC_0V: + hps = &refprism_2fa_2fb_1ec_0v; break; + case HP_PRISM_1FA_2FB_1EB_0V: + hps = &refprism_1fa_2fb_1eb_0v; break; + case HP_PRISM_2FB_3E_0V: + hps = &refprism_2fb_3e_0v; break; + case HP_PRISM_1FA_2FB_3E_0V: + hps = &refprism_1fa_2fb_3e_0v; break; + case HP_PRISM_2FA_2FB_3E_0V: + hps = &refprism_2fa_2fb_3e_0v; break; + case HP_PRISM_1FA_2E_0V: + hps = &refprism_1fa_2e_0v; break; + case HP_PRISM_2FA_2E_0V: + hps = &refprism_2fa_2e_0v; break; + case HP_PRISM_3E_0V: + hps = &refprism_3e_0v; break; + case HP_PRISM_1FA_3E_0V: + hps = &refprism_1fa_3e_0v; break; + case HP_PRISM_2FA_3E_0V: + hps = &refprism_2fa_3e_0v; break; + case HP_PRISM_3FB_0V: + hps = &refprism_3fb_0v; break; + case HP_PRISM_1FA_3FB_0V: + hps = &refprism_1fa_3fb_0v; break; + case HP_PRISM_2FA_3FB_0V: + hps = &refprism_2fa_3fb_0v; break; + // case HP_PRISM_3E_4EH: + // hps = &refprism_3e_4eh; break; + + + /*case HP_PRISM_1FB_1EB_0V: + hps = &refprism_1fb_1eb_0v; break; + case HP_PRISM_2F_0E_0V: + hps = &refprism_2f_0e_0v; break; + */ + + + case HP_PYRAMID: + hps = &refpyramid; break; + case HP_PYRAMID_0E_1V: + hps = &refpyramid_0e_1v; break; + case HP_PYRAMID_EDGES: + hps = &refpyramid_edges; break; + case HP_PYRAMID_1FB_0E_1VA: + hps = &refpyramid_1fb_0e_1va; break; + + + case HP_HEX: + hps = &refhex; break; + case HP_HEX_0E_1V: + hps = &refhex_0e_1v; break; + case HP_HEX_1E_1V: + hps = &refhex_1e_1v; break; + case HP_HEX_1E_0V: + hps = &refhex_1e_0v; break; + case HP_HEX_3E_0V: + hps = &refhex_3e_0v; break; + + case HP_HEX_1F_0E_0V: + hps = &refhex_1f_0e_0v; break; + case HP_HEX_1FA_1FB_0E_0V: + hps = &refhex_1fa_1fb_0e_0v; break; + } + + /* + if (type != HP_TET_1E_4V && type != HP_TET_1E_2VD) + { + if (hps->geom == 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<int> & edges, INDEX_2_HASHTABLE<int> & edgepoiclt_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & facepoint, int & levels, int & act_ref); + + bool ClassifyHPElements (Mesh & mesh, Array<HPRefElement> & elements, int & act_ref, int & levels); + + + void InitHPElements(Mesh & mesh, Array<HPRefElement> & 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<HPRefElement> & elements, + Refinement * ref, double fac1) + { + elements.SetAllocSize (5 * elements.Size()); + INDEX_2_HASHTABLE<int> newpts(elements.Size()+1); + INDEX_3_HASHTABLE<int> 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 + 1; + + 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; + newel.levelx = newel.levely = newel.levelz = newlevel; + 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<HPRefElement> & 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<HPRefElement> & 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<int> 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<HPRefElement> & 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<double>(p), 6.0); + cpucost = (ntet + nprism + nhex) * pow (static_cast<double>(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<double>(p1), 6.0) + << " (p1-3)^6 = " << pow ( static_cast<double>(max2(p1-3, 0)), 6.0) + << " p1^3 = " << pow ( static_cast<double>(p1), 3.0) + << " (p1-3)^3 = " << pow ( static_cast<double>(p1-3), 3.0) + << " [p1^3-(p1-3)^3]^2 = " << sqr (pow (static_cast<double>(p1),3.0) - pow ( static_cast<double>(p1-3), 3.0)) + << endl; + + p1 /= 2 +1; + memcosttet += pow (static_cast<double>(p1), 6.0); + memcostsctet += pow (static_cast<double>(p1), 6.0) - pow ( static_cast<double>(max2(p1-3, 1)), 6.0); + cpucosttet += pow (static_cast<double>(p1), 9.0); + break; + } + case HP_PRISM: + case HP_PRISM_SINGEDGE: + { + int p1 = maxlevel - el.level + 1; + p1 /= 2 +1; + memcostprism += pow (static_cast<double>(p1), 6.0); + memcostscprism += pow (static_cast<double>(p1), 6.0) - pow ( static_cast<double>(max2(p1-3, 1)), 6.0); + cpucostprism += pow (static_cast<double>(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<double>(p1), 4.0) * pow (static_cast<double>(p2), 2.0); + memcostschex += pow (static_cast<double>(p1), 6.0) - pow ( static_cast<double>(max2(p1-2, 0)), 6.0); + cpucosthex += pow (static_cast<double>(p1), 6.0) * pow (static_cast<double>(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<HPRefElement> & hpelements) + { + Array<int, 1> 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<MeshPoint, 1> 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<CurvedElements&> (mesh.coarsemesh->GetCurvedElements() ). + BuildCurvedElements (ref, mesh.GetCurvedElements().GetOrder()); + // #endif + + + delete mesh.hpelements; + mesh.hpelements = new Array<HPRefElement>; + + Array<HPRefElement> & hpelements = *mesh.hpelements; + + InitHPElements(mesh,hpelements); + + Array<int> 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<hpel.np;j++) + el.PNum(j+1) = hpel.pnums[j]; + el.hp_elnr = i; + el.SetIndex(hpel.index); + if(setorders) + el.SetOrder(act_ref+1,act_ref+1,0); + mesh.AddSurfaceElement(el); + break; + } + case HP_HEX: + case HP_TET: + case HP_PRISM: + case HP_PYRAMID: + { + Element el(hpel.np); + for(int j=0;j<hpel.np;j++) + el.PNum(j+1) = hpel.pnums[j]; + el.SetIndex(hpel.index); + el.hp_elnr = i; + if(setorders) + el.SetOrder(act_ref+1,act_ref+1,act_ref+1); + mesh.AddVolumeElement(el); + break; + } + + default: + PrintSysError ("hpref, backconversion failed for element ", + int(Get_HPRef_Struct (hpel.type) -> 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<mesh.GetNE(); i++) + { + Element el = mesh[i] ; + HPRefElement & hpel = hpelements[mesh[i].hp_elnr]; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (mesh[i].GetType()); + double dist[3] = {0,0,0}; + int ord_dir[3] = {0,0,0}; + int edge_dir[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; + int ned = 4; + + switch (mesh[i].GetType()) + { + case TET: + /* cout << " TET " ; + for(int k=0;k<4;k++) cout << el[k] << "\t" ; + cout << endl; */ + break; + case PRISM: + /* cout << " PRISM " ; + for(int k=0;k<6;k++) cout << el[k] << "\t" ; + cout << endl; */ + for(int l=6;l<9;l++) edge_dir[l] = 2; + ord_dir[2] = 2; + ned = 9; + break; + case HEX: + /* cout << " HEX " ; + for(int k=0;k<8;k++) cout << el[k] << "\t" ; + cout << endl; */ + for(int l=8;l<12; l++) edge_dir[l] = 2; + edge_dir[2] = edge_dir[3] = edge_dir[6] = edge_dir[7] = 1; + ord_dir[1] = 1; + ord_dir[2] = 2; + ned = 12; + break; + case PYRAMID: + /* cout << " PYRAMID " ; + for(int k=0;k<5;k++) cout << el[k] << "\t" ; + cout << endl; */ + for(int l=4;l<8;l++) edge_dir[l] = 2; + edge_dir[2] = edge_dir[3] = 1; + ord_dir[1] = 1; + ord_dir[2] = 2; + ned = 8; + break; + + + default: + cerr << "HPRefElement: illegal elementtype (2) " << mesh[i].GetType() << endl; + throw NgException ("HPRefElement: illegal elementtype (2)"); + + } + + for (int j=0;j<ned;j++) + { + + Vec<3> 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<mesh.GetNSE(); i++) + { + Element2d el = mesh[i] ; + HPRefElement & hpel = hpelements[mesh[i].hp_elnr]; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (mesh[i].GetType()); + double dist[3] = {0,0,0}; + int ord_dir[3] = {0,0,0}; + int edge_dir[4] = {0,0,0,0} ; + int ned = 3; + + if(mesh[i].GetType() == QUAD) + { + /* cout << " QUAD " ; + for(int k=0;k<4;k++) cout << el[k] << "\t" ; + cout << endl; */ + + edge_dir[2] = edge_dir[3] = 1; + ord_dir[1] = 1; + ned = 4; + } + /* else + { + cout << " TRIG " ; + for(int k=0;k<3;k++) cout << el[k] << "\t" ; + cout << endl; + } */ + + for (int j=0;j<ned;j++) + { + Vec<3> 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<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & facepoint, int & levels, int & act_ref) +{ + bool sing = 0; + if (mesh.GetDimension() == 3) + { + /* + // check, if point has as least 3 different surfs: + + Array<INDEX_3, PointIndex::BASE> 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<INDEX_3, PointIndex::BASE> 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 explicity 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<HPRefElement> & elements, int & act_ref, int & levels) + { + INDEX_2_HASHTABLE<int> edges(mesh.GetNSeg()+1); + BitArray edgepoint(mesh.GetNP()); + INDEX_2_HASHTABLE<int> 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<int> faces(mesh.GetNSE()+1); + INDEX_2_HASHTABLE<int> face_edges(mesh.GetNSE()+1); + INDEX_2_HASHTABLE<int> surf_edges(mesh.GetNSE()+1); + Array<int, PointIndex::BASE> 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<int> misses(10000); + misses = 0; + + (*testout) << "edgepoint_dom = " << endl << edgepoint_dom << endl; + + for( int i = 0; i<elements.Size(); i++) + { + // *testout << "classify element " << i << endl; + + HPRefElement & hpel = elements[i]; + HPRef_Struct * hprs = Get_HPRef_Struct (hpel.type); + HPRefElement old_el = elements[i]; + int dd=3; + + + if(act_ref !=1 && (hpel.type == HP_HEX || hpel.type == HP_PRISM || hpel.type == HP_TET + || hpel.type == HP_PYRAMID || hpel.type == HP_QUAD || hpel.type == HP_TRIG || hpel.type == HP_SEGM)) + continue; + + sing = 1; + switch (hprs->geom) + { + 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 = 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<hpel.np; j++) + { + for( int k=0; k<hpel.np; k++) + if(hpel[j] == old_el.pnums[k]) + { + for(int l=0;l<dd;l++) + hpel.param[j][l] = old_el.param[k][l]; + break; + } + } + + } + + + cout << "undefined elements update classification: " << cnt_undef << endl; + cout << "non-implemented in update classification: " << cnt_nonimplement << endl; + + for (int i = 0; i < misses.Size(); i++) + if (misses[i]) + cout << " in update classification missing case " << i << " occured " << misses[i] << " times" << endl; + + return(sing); + } +} + diff --git a/contrib/Netgen/libsrc/meshing/hprefinement.hpp b/contrib/Netgen/libsrc/meshing/hprefinement.hpp new file mode 100644 index 0000000000..f299ae8aa1 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hprefinement.hpp @@ -0,0 +1,319 @@ +#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, additonally 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; i<np ; i++) + { + pnums[i] = el[i]; + for(int l=0; l<np; l++) param[i][l] = el.param[i][l]; + } + switch(hprs->geom) + { + 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]; + +}; + + + +extern void HPRefinement (Mesh & mesh, Refinement * ref, int levels, + double fac1=0.125, bool setorders=true, bool ref_level = false); + + +#endif + diff --git a/contrib/Netgen/libsrc/meshing/improve2.cpp b/contrib/Netgen/libsrc/meshing/improve2.cpp new file mode 100644 index 0000000000..eea6c51137 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/improve2.cpp @@ -0,0 +1,854 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#include <opti.hpp> + +#ifndef SMALLLIB +//#ifndef NOTCL +//#include <visual.hpp> +//#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<SurfaceElementIndex> 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<Neighbour> neighbors(mesh.GetNSE()); + INDEX_2_HASHTABLE<trionedge> other(seia.Size() + 2); + + + Array<char> swapped(mesh.GetNSE()); + Array<int,PointIndex::BASE> pdef(mesh.GetNP()); + Array<double,PointIndex::BASE> 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<Vec3d> 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<SurfaceElementIndex> 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<SurfaceElementIndex,PointIndex::BASE> elementsonnode(np); + Array<SurfaceElementIndex> 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<bool,PointIndex::BASE> 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<Vec<3>,PointIndex::BASE> normals(np); + + for (PointIndex pi = PointIndex::BASE; + pi < np + PointIndex::BASE; 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; + + + mesh[pi1] = pnew; + PointGeomInfo gi; + bool gi_set(false); + + + Element2d *el1p(NULL); + int l = 0; + while(mesh[elementsonnode[pi1][l]].IsDeleted() && l<elementsonnode.EntrySize(pi1)) l++; + if(l<elementsonnode.EntrySize(pi1)) + el1p = &mesh[elementsonnode[pi1][l]]; + else + cerr << "OOPS!" << endl; + + for (l = 0; l < el1p->GetNP(); 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<Vec3d> ngs(3); + + (*mycout) << "Check Surface Approxiamtion" << endl; + (*testout) << "Check Surface Approxiamtion" << 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; + } + } + } + */ + } +} diff --git a/contrib/Netgen/libsrc/meshing/improve2.hpp b/contrib/Netgen/libsrc/meshing/improve2.hpp new file mode 100644 index 0000000000..4a6e49ea5e --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/improve2.hpp @@ -0,0 +1,102 @@ +#ifndef FILE_IMPROVE2 +#define FILE_IMPROVE2 + + + +/// +class MeshOptimize2d +{ + int faceindex; + int improveedges; + double metricweight; + int writestatus; + +public: + /// + MeshOptimize2d (); + /// + void ImproveMesh (Mesh & mesh2d, const MeshingParameters & mp); + void ImproveMeshJacobian (Mesh & mesh2d, const MeshingParameters & mp); + void ImproveVolumeMesh (Mesh & mesh); + void ProjectBoundaryPoints(Array<int> & surfaceindex, + const Array<Point<3>* > & from, Array<Point<3>* > & 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 Point3d & p1, + const Point3d & p2, + const Point3d & p3, + double metricweight, + double h); + +extern double CalcTriangleBadness (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + const Vec3d & n, + double metricweight, + double h); + +#endif + + diff --git a/contrib/Netgen/libsrc/meshing/improve2gen.cpp b/contrib/Netgen/libsrc/meshing/improve2gen.cpp new file mode 100644 index 0000000000..e5b65308a4 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/improve2gen.cpp @@ -0,0 +1,455 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#include <opti.hpp> + +namespace netgen +{ + + class ImprovementRule + { + public: + Array<Element2d> oldels; + Array<Element2d> newels; + Array<INDEX_2> deledges; + Array<int> incelsonnode; + Array<int> 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 << ": " <<flush; +// for(int j=0; j<el.GetNP(); j++) +// (*testout) << el[j] << " " << flush; +// (*testout) << "IsDeleted() " << el.IsDeleted()<< endl; +// } + + bool ok; + int olddef, newdef; + + Array<ImprovementRule*> rules; + Array<SurfaceElementIndex> elmap; + Array<int> elrot; + Array<PointIndex> pmap; + Array<PointGeomInfo> 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<int> mapped(rules.Size()); + Array<int> 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<int,PointIndex::BASE> elonnode(np); + Array<int,PointIndex::BASE> nelonnode(np); + TABLE<SurfaceElementIndex> 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<SurfaceElementIndex> 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 = -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<rule.deledges.Size(); i++) + { + ok = !mesh.IsSegment(pmap.Elem(rule.deledges[i].I1()), + pmap.Elem(rule.deledges[i].I2())); + } + + + + + if (!ok) continue; + + mapped[ri]++; + + olddef = 0; + for (int j = 1; j <= pmap.Size(); j++) + olddef += sqr (nelonnode[pmap.Get(j)]); + olddef += rule.bonus; + + newdef = 0; + for (int j = 1; j <= pmap.Size(); j++) + if (rule.reused.Get(j)) + newdef += sqr (nelonnode[pmap.Get(j)] + + rule.incelsonnode.Get(j)); + + if (newdef > 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"); + } + } + + + + +} diff --git a/contrib/Netgen/libsrc/meshing/improve3.cpp b/contrib/Netgen/libsrc/meshing/improve3.cpp new file mode 100644 index 0000000000..8a236aa201 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/improve3.cpp @@ -0,0 +1,2779 @@ +#include <mystdlib.h> + +#include "meshing.hpp" + +#ifdef SOLIDGEOM +#include <csg.hpp> +#endif +#include <opti.hpp> + +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) +{ + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + + TABLE<ElementIndex, PointIndex::BASE> elementsonnode(np); + Array<ElementIndex> hasonepi, hasbothpi; + + Array<double> oneperr; + Array<double> 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++) + { + 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<int> edgetested (np+1); + + int cnt = 0; + + for (ElementIndex ei = 0; ei < ne; ei++) + { + 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<ElementIndex> 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<ElementIndex> 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<ElementIndex> 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++) + 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.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) +{ + int j, k, l; + Point3d p1, p2, pnew; + + ElementIndex ei; + SurfaceElementIndex sei; + PointIndex pi1, pi2; + + double bad1, bad2, badmax, badlimit; + + + int cnt = 0; + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + + TABLE<ElementIndex,PointIndex::BASE> elementsonnode(np); + Array<ElementIndex> hasbothpoints; + + BitArray origpoint(np), boundp(np); + origpoint.Set(); + + Array<double> elerrs(ne); + BitArray illegaltet(ne); + illegaltet.Clear(); + + const char * savetask = multithread.task; + multithread.task = "Split Improve"; + + + PrintMessage (3, "SplitImprove"); + (*testout) << "start SplitImprove" << "\n"; + + Array<INDEX_3> locfaces; + + INDEX_2_HASHTABLE<int> edgetested (np); + + bad1 = 0; + badmax = 0; + for (ei = 0; ei < ne; ei++) + { + 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 (sei = 0; sei < mesh.GetNSE(); sei++) + for (j = 0; j < 3; j++) + boundp.Set (mesh[sei][j]); + + if (goal == OPT_QUALITY) + { + bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); + (*testout) << "Total badness = " << bad1 << endl; + } + + for (ei = 0; ei < ne; ei++) + for (j = 0; j < mesh[ei].GetNP(); j++) + elementsonnode.Add (mesh[ei][j], ei); + + + mesh.MarkIllegalElements(); + if (goal == OPT_QUALITY || goal == OPT_LEGAL) + { + int cntill = 0; + for (ei = 0; ei < ne; ei++) + { + // if (!LegalTet (volelements.Get(i))) + if (mesh[ei].flags.illegal) + { + cntill++; + illegaltet.Set (ei+1); + } + } + // (*mycout) << cntill << " illegal tets" << endl; + } + + + for (ei = 0; ei < ne; ei++) + { + if (multithread.terminate) + break; + + multithread.percent = 100.0 * (ei+1) / ne; + + bool ltestmode = 0; + + + if (elerrs[ei] < badlimit && !illegaltet.Test(ei+1)) continue; + + if ((goal == OPT_LEGAL) && + !illegaltet.Test(ei+1) && + CalcBad (mesh.Points(), mesh[ei], 0) < 1e3) + continue; + + + Element & elem = mesh[ei]; + + if (ltestmode) + { + (*testout) << "test el " << ei << endl; + for (j = 0; j < 4; j++) + (*testout) << elem[j] << " "; + (*testout) << endl; + } + + + for (j = 0; j < 6; j++) + { + + static const int tetedges[6][2] = + { { 0, 1 }, { 0, 2 }, { 0, 3 }, + { 1, 2 }, { 1, 3 }, { 2, 3 } }; + + pi1 = elem[tetedges[j][0]]; + pi2 = elem[tetedges[j][1]]; + + if (pi2 < pi1) Swap (pi1, pi2); + if (pi2 > elementsonnode.Size()) continue; + + 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+1)) continue; + edgetested.Set (i2, 1); + + hasbothpoints.SetSize (0); + for (k = 1; k <= elementsonnode.EntrySize(pi1); k++) + { + bool has1 = 0, has2 = 0; + + ElementIndex elnr = elementsonnode.Get(pi1, k); + Element & el = mesh[elnr]; + + for (l = 0; l < el.GetNP(); l++) + { + if (el[l] == pi1) has1 = 1; + if (el[l] == pi2) has2 = 1; + } + if (has1 && has2) + { // only once + for (l = 0; l < hasbothpoints.Size(); l++) + if (hasbothpoints[l] == elnr) + has1 = 0; + + if (has1) + hasbothpoints.Append (elnr); + } + } + + bad1 = 0; + for (k = 0; k < hasbothpoints.Size(); k++) + bad1 += CalcBad (mesh.Points(), mesh[hasbothpoints[k]], 0); + + + bool puretet = 1; + for (k = 0; k < hasbothpoints.Size(); k++) + if (mesh[hasbothpoints[k]].GetType() != TET) + puretet = 0; + if (!puretet) continue; + + p1 = mesh[pi1]; + 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 (k = 0; k < hasbothpoints.Size(); k++) + { + const Element & el = mesh[hasbothpoints[k]]; + + for (l = 0; l < 4; l++) + if (el[l] == pi1 || el[l] == pi2) + { + INDEX_3 i3; + Element2d face; + 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; + + 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); + + + int hpinew = mesh.AddPoint (pnew); + // ptyps.Append (INNERPOINT); + + for (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 (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 (k = 0; k < hasbothpoints.Size(); k++) + { + Element & oldel = mesh[hasbothpoints[k]]; + Element newel = oldel; + + newel.flags.illegal_valid = 0; + oldel.flags.illegal_valid = 0; + + for (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; + } + } + } + + + 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 (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) +{ + PointIndex pi1(0), pi2(0), 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<ElementIndex,PointIndex::BASE> elementsonnode(np); + + Array<ElementIndex> hasbothpoints; + + PrintMessage (3, "SwapImprove "); + (*testout) << "\n" << "Start SwapImprove" << endl; + + const char * savetask = multithread.task; + multithread.task = "Swap Improve"; + + // mesh.CalcSurfacesOfNode (); + + INDEX_3_HASHTABLE<int> 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 (int j = 0; j < mesh[ei].GetNP(); j++) + elementsonnode.Add (mesh[ei][j], ei); + + + // INDEX_2_HASHTABLE<int> edgeused(2 * ne + 5); + INDEX_2_CLOSED_HASHTABLE<int> 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; + + // int onlybedges = 1; + + for (int j = 0; j < 6; j++) + { + // loop over edges + + const Element & elemi = mesh[ei]; + if (elemi.IsDeleted()) continue; + + + // (*testout) << "check element " << elemi << endl; + + int mattyp = elemi.GetIndex(); + + 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); + + 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 + for (int l = 0; l < hasbothpoints.Size(); l++) + if (hasbothpoints[l] == elnr) + has1 = 0; + + if (has1) + hasbothpoints.Append (elnr); + } + } + + bool puretet = 1; + for (int k = 0; k < hasbothpoints.Size(); k++) + if (mesh[hasbothpoints[k]].GetType () != TET) + puretet = 0; + 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 = 1; k < 3; k++) + { + const Element & elemk = mesh[hasbothpoints[k]]; + bool has1 = 0; + for (int l = 0; l < 4; l++) + if (elemk[l] == pi4) + has1 = 1; + if (has1) + { + for (int l = 0; l < 4; l++) + if (elemk[l] != pi1 && elemk[l] != pi2 && elemk[l] != pi4) + pi5 = elemk[l]; + } + } + + if(pi5 == 0) + 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] = 0; + 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 = 0; + for (int k = 1; k < 4; k++) + { + const Element & elem = mesh[hasbothpoints[k]]; + bool has1 = 0; + for (int l = 0; l < 4; l++) + if (elem[l] == pi4) + has1 = 1; + if (has1) + { + for (int l = 0; l < 4; l++) + if (elem[l] != pi1 && elem[l] != pi2 && elem[l] != pi4) + pi5 = elem[l]; + } + } + + pi6 = 0; + for (int k = 1; k < 4; k++) + { + const Element & elem = mesh[hasbothpoints[k]]; + bool has1 = 0; + for (int l = 0; l < 4; l++) + if (elem[l] == pi3) + has1 = 1; + 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<PointIndex, 50> suroundpts(nsuround); + ArrayMem<char, 50> 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[0] = pi3; + suroundpts[1] = pi4; + + tetused = 0; + tetused[0] = 1; + + for (int l = 2; l < nsuround; l++) + { + int oldpi = suroundpts[l-1]; + int newpi = 0; + + for (int k = 0; k < nsuround && !newpi; k++) + if (!tetused[k]) + { + const Element & nel = mesh[hasbothpoints[k]]; + + for (int k2 = 0; k2 < 4 && !newpi; k2++) + if (nel[k2] == oldpi) + { + newpi = + nel[0] + nel[1] + nel[2] + nel[3] + - pi1 - pi2 - oldpi; + + tetused[k] = 1; + 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] = 0; + + } + } + } + } + + /* + 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; + + /* + 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<int,PointIndex::BASE>* > * idmaps) +{ + Array< Array<int,PointIndex::BASE>* > locidmaps; + const Array< Array<int,PointIndex::BASE>* > * 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<int,PointIndex::BASE>); + 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<ElementIndex,PointIndex::BASE> elementsonnode(np); + TABLE<SurfaceElementIndex,PointIndex::BASE> surfaceelementsonnode(np); + TABLE<int,PointIndex::BASE> surfaceindicesonnode(np); + + Array<ElementIndex> hasbothpoints; + Array<ElementIndex> 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<mesh[sei].GetNP(); j++) + { + surfaceelementsonnode.Add(mesh[sei][j], sei); + if(!surfaceindicesonnode[mesh[sei][j]].Contains(mesh[sei].GetIndex())) + surfaceindicesonnode.Add(mesh[sei][j],mesh[sei].GetIndex()); + } + + bool periodic; + int idnum(-1); + + // INDEX_2_HASHTABLE<int> edgeused(2 * ne + 5); + INDEX_2_CLOSED_HASHTABLE<int> 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 && k<used_idmaps->Size(); 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<hasbothpoints.Size(); k++) + // (*testout) << "hasbothpoints["<<k<<"]: " << mesh[hasbothpoints[k]] << endl; + + + SurfaceElementIndex sel1=-1,sel2=-1; + SurfaceElementIndex sel1other=-1,sel2other=-1; + for(int k = 0; k < surfaceelementsonnode[pi1].Size(); k++) + { + bool has1 = false, has2 = false; + SurfaceElementIndex elnr = surfaceelementsonnode[pi1][k]; + const Element2d & 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 && elnr != sel2) + { + sel1 = sel2; + sel2 = elnr; + } + } + + if(periodic) + { + for(int k = 0; k < surfaceelementsonnode[pi1other].Size(); k++) + { + bool has1 = false, has2 = false; + SurfaceElementIndex elnr = surfaceelementsonnode[pi1other][k]; + const Element2d & 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 && elnr != sel2other) + { + sel1other = sel2other; + sel2other = elnr; + } + } + } + else + { + sel1other = sel1; sel2other = sel2; + } + + //(*testout) << "sel1 " << sel1 << " sel2 " << sel2 << " el " << mesh[sel1] << " resp. " << mesh[sel2] << endl; + + PointIndex sp1(0), sp2(0); + PointIndex sp1other, sp2other; + for(int l=0; l<mesh[sel1].GetNP(); l++) + if(mesh[sel1][l] != pi1 && mesh[sel1][l] != pi2) + sp1 = mesh[sel1][l]; + for(int l=0; l<mesh[sel2].GetNP(); l++) + if(mesh[sel2][l] != pi1 && mesh[sel2][l] != pi2) + sp2 = mesh[sel2][l]; + + if(periodic) + { + sp1other = (*(*used_idmaps)[idnum])[sp1]; + sp2other = (*(*used_idmaps)[idnum])[sp2]; + + bool change = false; + for(int l=0; !change && l<mesh[sel1other].GetNP(); l++) + change = (sp2other == mesh[sel1other][l]); + + if(change) + { + SurfaceElementIndex aux = sel1other; + sel1other = sel2other; + sel2other = aux; + } + + } + else + { + sp1other = sp1; sp2other = sp2; + } + + Vec<3> 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<nsuround; i++) + { + bool done = false; + for(int jj=i; !done && jj<hasbothpoints.Size(); jj++) + { + for(int k=0; !done && k<4; k++) + if(mesh[hasbothpoints[jj]][k] == outerpoints[i]) + { + done = true; + for(int l=0; l<4; l++) + if(mesh[hasbothpoints[jj]][l] != pi1 && + mesh[hasbothpoints[jj]][l] != pi2 && + mesh[hasbothpoints[jj]][l] != outerpoints[i]) + outerpoints[i+1] = mesh[hasbothpoints[jj]][l]; + } + if(done) + { + ElementIndex aux = hasbothpoints[i]; + hasbothpoints[i] = hasbothpoints[jj]; + hasbothpoints[jj] = aux; + } + } + } + if(outerpoints[nsuround] != sp2) + { + cerr << "OJE OJE OJE" << endl; + (*testout) << "OJE OJE OJE" << endl; + (*testout) << "hasbothpoints: " << endl; + for(int ii=0; ii < hasbothpoints.Size(); ii++) + { + (*testout) << mesh[hasbothpoints[ii]] << endl; + for(int jj=0; jj<mesh[hasbothpoints[ii]].GetNP(); jj++) + if(mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] > 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<nsuroundother; i++) + { + bool done = false; + for(int jj=i; !done && jj<hasbothpointsother.Size(); jj++) + { + for(int k=0; !done && k<4; k++) + if(mesh[hasbothpointsother[jj]][k] == outerpointsother[i]) + { + done = true; + for(int l=0; l<4; l++) + if(mesh[hasbothpointsother[jj]][l] != pi1other && + mesh[hasbothpointsother[jj]][l] != pi2other && + mesh[hasbothpointsother[jj]][l] != outerpointsother[i]) + outerpointsother[i+1] = mesh[hasbothpointsother[jj]][l]; + } + if(done) + { + ElementIndex aux = hasbothpointsother[i]; + hasbothpointsother[i] = hasbothpointsother[jj]; + hasbothpointsother[jj] = aux; + } + } + } + if(nsuroundother > 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<mesh[hasbothpoints[ii]].GetNP(); jj++) + if(mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] > 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<mesh[hasbothpointsother[ii]].GetNP(); jj++) + if(mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][0] > 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<hasbothpoints.Size(); i++) + bad1 += CalcBad(mesh.Points(), mesh[hasbothpoints[i]],h); + for(int i=0; i<hasbothpointsother.Size(); i++) + bad1 += CalcBad(mesh.Points(), mesh[hasbothpointsother[i]],h); + bad1 /= double(hasbothpoints.Size() + hasbothpointsother.Size()); + + + int startpoints,startpointsother; + + + if(outerpoints.Size() == 3) + startpoints = 1; + else if(outerpoints.Size() == 4) + startpoints = 2; + else + startpoints = outerpoints.Size(); + + if(outerpointsother.Size() == 3) + startpointsother = 1; + else if(outerpointsother.Size() == 4) + startpointsother = 2; + else + startpointsother = outerpointsother.Size(); + + + Array < Array < Element* > * > 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<startpoints; i++) + { + newelts[i] = new Array <Element*>(2*(nsuround-1)); + + for(int jj=0; jj<nsuround-1; jj++) + { + (*newelts[i])[2*jj] = new Element(TET); + (*newelts[i])[2*jj+1] = new Element(TET); + Element & newel1 = *((*newelts[i])[2*jj]); + Element & newel2 = *((*newelts[i])[2*jj+1]); + + newel1[0] = pi1; + newel1[1] = outerpoints[i]; + newel1[2] = outerpoints[(i+jj+1)%outerpoints.Size()]; + newel1[3] = outerpoints[(i+jj+2)%outerpoints.Size()]; + + newel2[0] = pi2; + newel2[1] = outerpoints[i]; + newel2[2] = outerpoints[(i+jj+2)%outerpoints.Size()]; + newel2[3] = outerpoints[(i+jj+1)%outerpoints.Size()]; + + + //(*testout) << "j " << j << " newel1 " << newel1[0] << " "<< newel1[1] << " "<< newel1[2] << " "<< newel1[3] << endl + // << " newel2 " << newel2[0] << " "<< newel2[1] << " "<< newel2[2] << " "<< newel2[3] << endl; + + newel1.SetIndex(mattype); + newel2.SetIndex(mattype); + + } + + bool wrongorientation = true; + for(int jj = 0; wrongorientation && jj<newelts[i]->Size(); jj++) + wrongorientation = wrongorientation && WrongOrientation(mesh.Points(), *(*newelts[i])[jj]); + + currbad = 0; + + for(int jj=0; jj<newelts[i]->Size(); jj++) + { + if(wrongorientation) + Swap((*(*newelts[i])[jj])[2],(*(*newelts[i])[jj])[3]); + + + // not two new faces on same surface + Array<int> face_index; + for(int k = 0; k<surfaceindicesonnode[(*(*newelts[i])[jj])[0]].Size(); k++) + face_index.Append(surfaceindicesonnode[(*(*newelts[i])[jj])[0]][k]); + + for(int k=1; k<4; k++) + { + for(int l=0; l<face_index.Size(); l++) + { + if(face_index[l] != -1 && + !(surfaceindicesonnode[(*(*newelts[i])[jj])[k]].Contains(face_index[l]))) + face_index[l] = -1; + } + + } + + for(int k=0; k<face_index.Size(); k++) + if(face_index[k] != -1) + currbad += 1e12; + + + currbad += CalcBad(mesh.Points(),*(*newelts[i])[jj],h); + + + } + + //currbad /= double(newelts[i]->Size()); + + + + if(currbad < minbad) + { + minbad = currbad; + minpos = i; + } + + } + + if(startpointsother == 0) + minbadother = 0; + + for(int i=0; i<startpointsother; i++) + { + neweltsother[i] = new Array <Element*>(2*(nsuroundother)); + + for(int jj=0; jj<nsuroundother; jj++) + { + (*neweltsother[i])[2*jj] = new Element(TET); + (*neweltsother[i])[2*jj+1] = new Element(TET); + Element & newel1 = *((*neweltsother[i])[2*jj]); + Element & newel2 = *((*neweltsother[i])[2*jj+1]); + + newel1[0] = pi1other; + newel1[1] = outerpointsother[i]; + newel1[2] = outerpointsother[(i+jj+1)%outerpointsother.Size()]; + newel1[3] = outerpointsother[(i+jj+2)%outerpointsother.Size()]; + + newel2[0] = pi2other; + newel2[1] = outerpointsother[i]; + newel2[2] = outerpointsother[(i+jj+2)%outerpointsother.Size()]; + newel2[3] = outerpointsother[(i+jj+1)%outerpointsother.Size()]; + + + //(*testout) << "j " << j << " newel1 " << newel1[0] << " "<< newel1[1] << " "<< newel1[2] << " "<< newel1[3] << endl + // << " newel2 " << newel2[0] << " "<< newel2[1] << " "<< newel2[2] << " "<< newel2[3] << endl; + + newel1.SetIndex(othermattype); + newel2.SetIndex(othermattype); + + } + + bool wrongorientation = true; + for(int jj = 0; wrongorientation && jj<neweltsother[i]->Size(); jj++) + wrongorientation = wrongorientation && WrongOrientation(mesh.Points(), *(*neweltsother[i])[jj]); + + currbad = 0; + + for(int jj=0; jj<neweltsother[i]->Size(); 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<hasbothpoints.Size(); i++) + { + mesh[hasbothpoints[i]] = *(*newelts[minpos])[i]; + + for(int l=0; l<4; l++) + elementsonnode.Add((*(*newelts[minpos])[i])[l],hasbothpoints[i]); + } + + for(int i=hasbothpoints.Size(); i<(*newelts[minpos]).Size(); i++) + { + ElementIndex ni = mesh.AddVolumeElement(*(*newelts[minpos])[i]); + + for(int l=0; l<4; l++) + elementsonnode.Add((*(*newelts[minpos])[i])[l],ni); + } + + if(hasbothpointsother.Size() > 0) + { + for(int i=0; i<hasbothpointsother.Size(); i++) + { + mesh[hasbothpointsother[i]] = *(*neweltsother[minposother])[i]; + for(int l=0; l<4; l++) + elementsonnode.Add((*(*neweltsother[minposother])[i])[l],hasbothpointsother[i]); + } + + for(int i=hasbothpointsother.Size(); i<(*neweltsother[minposother]).Size(); i++) + { + ElementIndex ni = mesh.AddVolumeElement(*(*neweltsother[minposother])[i]); + for(int l=0; l<4; l++) + elementsonnode.Add((*(*neweltsother[minposother])[i])[l],ni); + } + } + + + + } + + for(int i=0; i<newelts.Size(); i++) + { + for(int jj=0; jj<newelts[i]->Size(); jj++) + delete (*newelts[i])[jj]; + delete newelts[i]; + } + + for(int i=0; i<neweltsother.Size(); i++) + { + for(int jj=0; jj<neweltsother[i]->Size(); jj++) + delete (*neweltsother[i])[jj]; + delete neweltsother[i]; + } + + } + } + + PrintMessage (5, cnt, " swaps performed"); + + + for(int i=0; i<locidmaps.Size(); i++) + delete locidmaps[i]; + + + mesh.Compress (); + + multithread.task = savetask; +} + + + + + + + + +/* + 2 -> 3 conversion +*/ + + +void MeshOptimize3d :: SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal) +{ + 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<ElementIndex, PointIndex::BASE> elementsonnode(np); + TABLE<SurfaceElementIndex, PointIndex::BASE> 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; + + // 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<ElementIndex> 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<INDEX_2> 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"; + } + +*/ +} diff --git a/contrib/Netgen/libsrc/meshing/improve3.hpp b/contrib/Netgen/libsrc/meshing/improve3.hpp new file mode 100644 index 0000000000..41001e8426 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/improve3.hpp @@ -0,0 +1,125 @@ +#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<int,PointIndex::BASE>* > * 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<MinFunction*> 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<INDEX_3> & faces; + const MeshingParameters & mp; + double h; +public: + PointFunction1 (Mesh::T_POINTS & apoints, + const Array<INDEX_3> & 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<INDEX> elementsonpoint; + PointIndex actpind; + + bool onplane; + Vec<3> nv; + +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; + + inline void SetNV(const Vec<3> & anv) {nv = anv; onplane = true;} + inline void UnSetNV(void) {onplane = false;} +}; + + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/localh.cpp b/contrib/Netgen/libsrc/meshing/localh.cpp new file mode 100644 index 0000000000..99767360be --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/localh.cpp @@ -0,0 +1,708 @@ +#include <mystdlib.h> +#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 (const Point3d & pmin, const Point3d & pmax, double agrading) + { + double x1[3], x2[3]; + double hmax; + + boundingbox = Box3d (pmin, pmax); + grading = agrading; + + // a small enlargement, non-regular points + double val = 0.0879; + for (int i = 1; i <= 3; i++) + { + x1[i-1] = (1 + val * i) * pmin.X(i) - val * i * pmax.X(i); + x2[i-1] = 1.1 * pmax.X(i) - 0.1 * pmin.X(i); + } + + hmax = x2[0] - x1[0]; + for (int i = 1; i <= 2; i++) + if (x2[i] - x1[i] > hmax) + hmax = x2[i] - x1[i]; + + for (int i = 0; i <= 2; i++) + x2[i] = x1[i] + hmax; + + root = new GradingBox (x1, x2); + boxes.Append (root); + } + + + LocalH :: LocalH (const Box<3> & box, double agrading) + { + Point3d pmin = box.PMin(); + Point3d pmax = box.PMax(); + + double x1[3], x2[3]; + double hmax; + + boundingbox = Box3d (pmin, pmax); + grading = agrading; + + // a small enlargement, non-regular points + double val = 0.0879; + for (int i = 1; i <= 3; i++) + { + x1[i-1] = (1 + val * i) * pmin.X(i) - val * i * pmax.X(i); + x2[i-1] = 1.1 * pmax.X(i) - 0.1 * pmin.X(i); + } + + hmax = x2[0] - x1[0]; + for (int i = 1; i <= 2; i++) + if (x2[i] - x1[i] > hmax) + hmax = x2[i] - x1[i]; + + for (int i = 0; i <= 2; 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 (const Point3d & p, double h) + { + /* + (*testout) << "Set h at " << p << " to " << h << endl; + if (h < 1e-8) + { + cout << "do not set h to " << h << endl; + return; + } + */ + + if (fabs (p.X() - root->xmid[0]) > root->h2 || + fabs (p.Y() - root->xmid[1]) > root->h2 || + fabs (p.Z() - root->xmid[2]) > root->h2) + return; + + /* + if (p.X() < root->x1[0] || p.X() > root->x2[0] || + p.Y() < root->x1[1] || p.Y() > root->x2[1] || + p.Z() < root->x1[2] || p.Z() > root->x2[2]) + 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.X() > box->xmid[0]) childnr += 1; + if (p.Y() > box->xmid[1]) childnr += 2; + if (p.Z() > box->xmid[2]) childnr += 4; + nbox = box->childs[childnr]; + }; + + + while (2 * box->h2 > h) + { + childnr = 0; + if (p.X() > box->xmid[0]) childnr += 1; + if (p.Y() > box->xmid[1]) childnr += 2; + if (p.Z() > 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; + + Point3d np; + for (int i = 1; i <= 3; i++) + { + np = p; + np.X(i) = p.X(i) + hbox; + SetH (np, hnp); + + np.X(i) = p.X(i) - hbox; + SetH (np, hnp); + } + } + + + + double LocalH :: GetH (const Point3d & x) const + { + const GradingBox * box = root; + + while (1) + { + int childnr = 0; + if (x.X() > box->xmid[0]) childnr += 1; + if (x.Y() > box->xmid[1]) childnr += 2; + if (x.Z() > 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 (const Point3d & pmin, const Point3d & pmax) const + { + Point3d pmin2, pmax2; + for (int j = 1; j <= 3; j++) + if (pmin.X(j) < pmax.X(j)) + { pmin2.X(j) = pmin.X(j); pmax2.X(j) = pmax.X(j); } + else + { pmin2.X(j) = pmax.X(j); pmax2.X(j) = pmin.X(j); } + + return GetMinHRec (pmin2, pmax2, root); + } + + + double LocalH :: GetMinHRec (const Point3d & pmin, const Point3d & pmax, + const GradingBox * box) const + { + 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 (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)) + { + 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<int> faceinds(nf); + Array<Box3d> 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<Box3d> & faceboxes, + Array<int> & 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<int, 100> faceused; + ArrayMem<int, 100> faceused2; + ArrayMem<int, 100> 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)) + { + int nf = adfront->GetNFL(); + + 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; + + Array<int> faceinds(nf); + Array<Box<3> > 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<Box<3> > & faceboxes, + Array<int> & 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<int, 100> faceused; + ArrayMem<int, 100> faceused2; + ArrayMem<int, 100> facenotused; + + + 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 + { + Point<2> c2d (c.X(), c.Y()); + Point<2> cf2d (cf.X(), cf.Y()); + if (adfront->SameSide (c2d, cf2d, &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 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<Point<3> > & points) + { + for (int i = 0; i < boxes.Size(); i++) + if (boxes[i] -> flags.isinner) + points.Append ( boxes[i] -> PMid() ); + } + + + void LocalH :: GetOuterPoints (Array<Point<3> > & 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; + } +} diff --git a/contrib/Netgen/libsrc/meshing/localh.hpp b/contrib/Netgen/libsrc/meshing/localh.hpp new file mode 100644 index 0000000000..ee279c8696 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/localh.hpp @@ -0,0 +1,187 @@ +#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; } + + 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<GradingBox*> boxes; + /// + Box3d boundingbox; + public: + /// + LocalH (const Point3d & pmin, const Point3d & pmax, double grading); + /// + LocalH (const Box<3> & box, double grading); + /// + ~LocalH(); + /// + void Delete(); + /// + void SetGrading (double agrading) { grading = agrading; } + /// + void SetH (const Point3d & x, double h); + /// + double GetH (const Point3d & x) const; + /// minimal h in box (pmin, pmax) + double GetMinH (const Point3d & pmin, const Point3d & 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<Point<3> > & points); + + /// get points in outer closure + void GetOuterPoints (Array<Point<3> > & points); + + /// + void Convexify (); + /// + int GetNBoxes () { return boxes.Size(); } + const Box3d & 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<Box3d> & faceboxes, + Array<int> & finds, int nfinbox); + + + + void FindInnerBoxesRec ( int (*inner)(const Point<2> & p), + GradingBox * box); + + /// + void FindInnerBoxesRec2 (GradingBox * box, + class AdFront2 * adfront, + Array<Box<3> > & faceboxes, + Array<int> & 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 diff --git a/contrib/Netgen/libsrc/meshing/meshclass.cpp b/contrib/Netgen/libsrc/meshing/meshclass.cpp new file mode 100644 index 0000000000..430a95ff85 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshclass.cpp @@ -0,0 +1,5648 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + + Mesh :: Mesh () + { + // 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); + +#ifdef PARALLEL + paralleltop = new ParallelMeshTopology (*this); +#endif + } + + + Mesh :: ~Mesh() + { + 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++ ) + if ( bcnames[i] ) delete bcnames[i]; + +#ifdef PARALLEL + delete paralleltop; +#endif + } + + + Mesh & Mesh :: operator= (const Mesh & mesh2) + { + points = mesh2.points; + // eltyps = mesh2.eltyps; + segments = mesh2.segments; + surfelements = mesh2.surfelements; + volelements = mesh2.volelements; + lockedpoints = mesh2.lockedpoints; + facedecoding = mesh2.facedecoding; + dimension = mesh2.dimension; + + 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; + + 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); + 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]; + +#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) + { + NgLock lock(mutex); + lock.Lock(); + + timestamp = NextTimeStamp(); + + PointIndex pi = points.Size() + PointIndex::BASE; + points.Append ( MeshPoint (p, layer, INNERPOINT) ); + +#ifdef PARALLEL + points.Last().SetGhost(0); +#endif + + lock.UnLock(); + + return pi; + } + + PointIndex Mesh :: AddPoint (const Point3d & p, int layer, POINTTYPE type) + { + NgLock lock(mutex); + lock.Lock(); + + timestamp = NextTimeStamp(); + + PointIndex pi = points.Size() + PointIndex::BASE; + points.Append ( MeshPoint (p, layer, type) ); + +#ifdef PARALLEL + points.Last().SetGhost(0); +#endif + + 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) ); + + points.Last().SetGhost(isghost); + + 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) ); + + points.Last().SetGhost(isghost); + + 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 > 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; + +#ifdef PARALLEL + surfelements.Last().SetGhost ( el.IsGhost() ); +#endif + + lock.UnLock(); + return si; + } + + + 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; + +#ifdef PARALLEL + volelements.Last().SetGhost ( el.IsGhost() ); +#endif + + // while (volelements.Size() > eltyps.Size()) + // eltyps.Append (FREEELEMENT); + + timestamp = NextTimeStamp(); + + lock.UnLock(); + return ve; + } + + + + + + + void Mesh :: Save (const string & filename) const + { + + ofstream outfile(filename.c_str()); + + Save(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.width(8); + outfile << GetFaceDescriptor((*this)[sei].GetIndex ()).SurfNr()+1; + outfile.width(8); + outfile << GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty(); + outfile.width(8); + outfile << GetFaceDescriptor((*this)[sei].GetIndex ()).DomainIn(); + outfile.width(8); + outfile << GetFaceDescriptor((*this)[sei].GetIndex ()).DomainOut(); + } + else + outfile << " 0 0 0"; + + Element2d sel = (*this)[sei]; + if (invertsurf) + sel.Invert(); + + outfile.width(8); + outfile << sel.GetNP(); + + for (j = 0; j < sel.GetNP(); j++) + { + outfile.width(8); + outfile << sel[j]; + } + + + switch (geomtype) + { + case GEOM_STL: + for (j = 1; j <= sel.GetNP(); j++) + { + outfile.width(7); + outfile << " " << sel.GeomInfoPi(j).trignum; + } + break; + case GEOM_OCC: case GEOM_ACIS: + for (j = 1; j <= sel.GetNP(); j++) + { + outfile.width(7); + outfile << " " << sel.GeomInfoPi(j).u; + outfile << " " << sel.GeomInfoPi(j).v; + } + break; + default: + ; // outfile << "\n"; + } + + + 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.width(8); + outfile << (*this)[ei].GetIndex(); + outfile.width(8); + outfile << (*this)[ei].GetNP(); + + Element el = (*this)[ei]; + if (inverttets) + el.Invert(); + + /* + for (j = 0; j < el.GetNP(); j++) + for (int k = 0; k < el.GetNP()-1; k++) + if (el[k] > el[k+1]) swap (el[k], el[k+1]); + */ + + for (j = 0; j < el.GetNP(); j++) + { + outfile.width(8); + 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<INDEX_2> 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) && strlen (materials.Get(i))) + cntmat++; + + if (cntmat) + { + outfile << "materials" << endl; + outfile << cntmat << endl; + for (i = 1; i <= materials.Size(); i++) + if (materials.Get(i) && strlen (materials.Get(i))) + 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; + } + + /* + if ( GetDimension() == 2 ) + { + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment (i); + if ( ! bcprops.Contains(seg.si) && seg.GetBCName() != "" ) + { + bcprops.Append(seg.si); + cntbcnames++; + } + } + } + else + { + for (sei = 0; sei < GetNSE(); sei++) + { + if ((*this)[sei].GetIndex()) + { + int bcp = GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty(); + string name = GetFaceDescriptor((*this)[sei].GetIndex ()).BCName(); + if ( !bcprops.Contains(bcp) && + name != "" ) + { + bcprops.Append(bcp); + cntbcnames++; + } + } + } + } + + bcprops.SetSize(0); + if ( cntbcnames ) + { + outfile << "\nbcnames" << endl << cntbcnames << endl; + if ( GetDimension() == 2 ) + { + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment (i); + if ( ! bcprops.Contains(seg.si) && seg.GetBCName() != "" ) + { + bcprops.Append(seg.si); + outfile << seg.si << "\t" << seg.GetBCName() << endl; + } + } + } + else + { + for (sei = 0; sei < GetNSE(); sei++) + { + if ((*this)[sei].GetIndex()) + { + int bcp = GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty(); + string name = GetFaceDescriptor((*this)[sei].GetIndex ()).BCName(); + if ( !bcprops.Contains(bcp) && + name != "" ) + { + bcprops.Append(bcp); + outfile << bcp << "\t" << name << endl; + } + } + } + } + outfile << endl << endl; + } + */ + + int cnt_sing = 0; + for (PointIndex pi = PointIndex::BASE; pi < GetNP()+PointIndex::BASE; pi++) + if ((*this)[pi].Singularity()>=1.) cnt_sing++; + + if (cnt_sing) + { + outfile << "singular_points" << endl << cnt_sing << endl; + for (PointIndex pi = PointIndex::BASE; pi < GetNP()+PointIndex::BASE; 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; + } + } + + } + + + + void Mesh :: Load (const string & filename) + { + + ifstream infile(filename.c_str()); + if (!infile.good()) + throw NgException ("mesh file not found"); + + Load(infile); + } + + + + + void Mesh :: Load (istream & infile) + { + + 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"); + 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 (!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 (strcmp (str, "surfaceelementsgi") == 0) + for (int j = 1; j <= nep; j++) + infile >> tri.GeomInfoPi(j).trignum; + + if (strcmp (str, "surfaceelementsuv") == 0) + 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; + int hi, nep; + infile >> hi; + if (hi == 0) hi = 1; + el.SetIndex(hi); + infile >> nep; + el.SetNP(nep); + + 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); + } + } + + if (strcmp (str, "identifications") == 0) + { + infile >> n; + 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; + 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<int,0> 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, "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 (); + // BuildConnectedNodes (); + topology -> Update(); + clusters -> Update(); + + SetNextMajorTimeStamp(); + // PrintMemInfo (cout); + + +#ifdef PARALLEL + if ( ntasks > 1 ) + { + // for parallel processing + Distribute (); + return; + } +#endif + + } + + + + + + 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; + seg.edgenr = seg.edgenr + oldne; + 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; + 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<int> + (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(); + + 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(); + if (sel.GetNP() <= 4) + boundaryedges->Set (i2, 1); + } + } + + + 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 () + { + int i, j, k; + SurfaceElementIndex sei; + + surfacesonnode.SetSize (GetNP()); + + delete boundaryedges; + boundaryedges = NULL; + + delete surfelementht; + delete segmentht; + + /* + surfelementht = new INDEX_3_HASHTABLE<int> (GetNSE()/4 + 1); + segmentht = new INDEX_2_HASHTABLE<int> (GetNSeg() + 1); + */ + + surfelementht = new INDEX_3_CLOSED_HASHTABLE<int> (3*GetNSE() + 1); + segmentht = new INDEX_2_CLOSED_HASHTABLE<int> (3*GetNSeg() + 1); + + for (sei = 0; sei < GetNSE(); sei++) + { + const Element2d & sel = surfelements[sei]; + if (sel.IsDeleted()) continue; + + int si = sel.GetIndex(); + + for (j = 0; j < sel.GetNP(); j++) + { + PointIndex pi = sel[j]; + bool found = 0; + for (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(); + */ + 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 -> Set (i3, sei); // war das wichtig ??? sel.GetIndex()); + } + + int np = GetNP(); + + if (dimension == 3) + { + for (PointIndex pi = PointIndex::BASE; + pi < np+PointIndex::BASE; pi++) + points[pi].SetType (INNERPOINT); + + if (GetNFD() == 0) + { + for (sei = 0; sei < GetNSE(); sei++) + { + const Element2d & sel = surfelements[sei]; + if (sel.IsDeleted()) continue; + for (j = 0; j < sel.GetNP(); j++) + { + PointIndex pi = SurfaceElement(sei)[j]; + points[pi].SetType(FIXEDPOINT); + } + } + } + else + { + for (sei = 0; sei < GetNSE(); sei++) + { + const Element2d & sel = surfelements[sei]; + if (sel.IsDeleted()) continue; + for (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 (i = 0; i < segments.Size(); i++) + { + const Segment & seg = segments[i]; + for (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 (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 (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 int timer = NgProfiler::CreateTimer ("Mesh::FindOpenElements"); + NgProfiler::RegionTimer reg (timer); + + int np = GetNP(); + int ne = GetNE(); + int nse = GetNSE(); + + Array<int,PointIndex::BASE> 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<ElementIndex,PointIndex::BASE> 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<char, 1> 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<SurfaceElementIndex,PointIndex::BASE> 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<INDEX_2> faceht(100); + openelements.SetSize(0); + + for (PointIndex pi = PointIndex::BASE; pi < np+PointIndex::BASE; pi++) + if (selsonpoint[pi].Size()+elsonpoint[pi].Size()) + { + faceht.SetSize (2 * selsonpoint[pi].Size() + 4 * elsonpoint[pi].Size()); + + FlatArray<SurfaceElementIndex> row = selsonpoint[pi]; + for (ii = 0; ii < row.Size(); ii++) + { + hel = SurfaceElement(row[ii]); + 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<ElementIndex> 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++) + { + 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); + 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++) + { + int pi = sel.PNum(j); + if (pi < points.Size()+PointIndex::BASE) + 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 elemetns + // hash index: pnum1-2 + // hash data : surfnr, surfel-nr (pos) or segment nr(neg) + INDEX_2_HASHTABLE<INDEX_2> faceht(4 * GetNSE()+GetNSeg()+1); + + PrintMessage (5, "Test Opensegments"); + for (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 (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; + } + } + } + + + for (i = 1; i <= GetNSE(); i++) + { + const Element2d & el = SurfaceElement(i); + if (el.IsDeleted()) continue; + + if (surfnr == 0 || el.GetIndex() == surfnr) + { + for (j = 1; j <= el.GetNP(); j++) + { + INDEX_2 seg (el.PNumMod(j), el.PNumMod(j+1)); + INDEX_2 data; + + if (seg.I1() <= 0 || seg.I2() <= 0) + 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 + { + PrintSysError ("hash table si not fitting for segment: ", + seg.I1(), "-", seg.I2(), " other = ", + data.I2()); + } + } + else + { + Swap (seg.I1(), seg.I2()); + data.I1() = el.GetIndex(); + data.I2() = i; + + faceht.Set (seg, data); + } + } + } + } + + (*testout) << "open segments: " << endl; + opensegments.SetSize(0); + for (i = 1; i <= faceht.GetNBags(); i++) + for (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 (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 (i = 1; i <= points.Size(); i++) + points.Elem(i).SetType(SURFACEPOINT); + + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment (i); + points[seg[0]].SetType(EDGEPOINT); + points[seg[1]].SetType(EDGEPOINT); + } + for (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 i, j; + int np = GetNP(); + + FindOpenSegments(); + BitArray frontpoints(np); + + frontpoints.Clear(); + for (i = 1; i <= GetNOpenSegments(); i++) + { + const Segment & seg = GetOpenSegment(i); + frontpoints.Set (seg[0]); + frontpoints.Set (seg[1]); + } + + for (i = 1; i <= GetNSE(); i++) + { + Element2d & sel = surfelements.Elem(i); + int remove = 0; + for (j = 1; j <= sel.GetNP(); j++) + if (frontpoints.Test(sel.PNum(j))) + remove = 1; + if (remove) + sel.PNum(1) = 0; + } + + for (i = surfelements.Size(); i >= 1; i--) + { + if (surfelements.Elem(i).PNum(1) == 0) + { + 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<int,PointIndex::BASE> 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 (const Point3d & pmin, const Point3d & pmax, double grading) + { + Point3d c = Center (pmin, pmax); + double d = max3 (pmax.X()-pmin.X(), + pmax.Y()-pmin.Y(), + pmax.Z()-pmin.Z()); + d /= 2; + Point3d pmin2 = c - Vec3d (d, d, d); + Point3d pmax2 = c + Vec3d (d, d, d); + + + delete lochfunc; + lochfunc = new LocalH (pmin2, pmax2, grading); + } + + 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<double> & 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) + { + 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<GetNP()+PointIndex::BASE; j++) + { + const Point3d & p1 = points[i]; + const Point3d & p2 = points[j]; + hl = Dist(p1,p2); + RestrictLocalH(p1,hl); + RestrictLocalH(p2,hl); + //cout << "restricted h at " << p1 << " and " << p2 << " to " << hl << endl; + } + } + + + } + + + void Mesh :: CalcLocalHFromSurfaceCurvature (double grading, double elperr) + { + PrintMessage (3, "Calculating local h from surface curvature"); + + if (!lochfunc) + { + Point3d pmin, pmax; + GetBox (pmin, pmax); + + // SetLocalH (pmin, pmax, mparam.grading); + SetLocalH (pmin, pmax, grading); + } + + + INDEX_2_HASHTABLE<int> edges(3 * GetNP() + 2); + INDEX_2_HASHTABLE<int> 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<Vec3d> 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 char * meshsizefilename) + { + // Philippose - 10/03/2009 + // Improve error checking when loading and reading + // the local mesh size file + + if (!meshsizefilename) return; + + ifstream msf(meshsizefilename); + + // 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 = PointIndex::BASE; + pi < GetNP()+PointIndex::BASE; 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 = PointIndex::BASE; + pi < GetNP()+PointIndex::BASE; 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 () + { + int i, j; + Array<int,PointIndex::BASE> op2np(GetNP()); + Array<MeshPoint> hpoints; + BitArrayChar<PointIndex::BASE> 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 (i = 0; i < volelements.Size(); i++) + if (volelements[i][0] <= PointIndex::BASE-1 || + volelements[i].IsDeleted()) + { + volelements.Delete(i); + i--; + } + + + for (i = 0; i < surfelements.Size(); i++) + if (surfelements[i].IsDeleted()) + { + surfelements.Delete(i); + i--; + } + + for (i = 0; i < segments.Size(); i++) + if (segments[i][0] <= PointIndex::BASE-1) + { + segments.Delete(i); + i--; + } + + pused.Clear(); + for (i = 0; i < volelements.Size(); i++) + { + const Element & el = volelements[i]; + for (j = 0; j < el.GetNP(); j++) + pused.Set (el[j]); + } + + for (i = 0; i < surfelements.Size(); i++) + { + const Element2d & el = surfelements[i]; + for (j = 0; j < el.GetNP(); j++) + pused.Set (el[j]); + } + + for (i = 0; i < segments.Size(); i++) + { + const Segment & seg = segments[i]; + pused.Set (seg[0]); + pused.Set (seg[1]); + } + + for (i = 0; i < openelements.Size(); i++) + { + const Element2d & el = openelements[i]; + for (j = 0; j < el.GetNP(); j++) + pused.Set(el[j]); + } + + for (i = 0; i < lockedpoints.Size(); i++) + pused.Set (lockedpoints[i]); + + + /* + // compress points doesnt 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 (i = PointIndex::BASE; + i < points.Size()+PointIndex::BASE; i++) + if (pused.Test(i)) + { + npi++; + op2np[i] = npi; + hpoints.Append (points[i]); + } + else + op2np[i] = -1; + + + + points.SetSize(0); + for (i = 0; i < hpoints.Size(); i++) + points.Append (hpoints[i]); + + + for (i = 1; i <= volelements.Size(); i++) + { + Element & el = VolumeElement(i); + for (j = 0; j < el.GetNP(); j++) + el[j] = op2np[el[j]]; + } + + for (i = 1; i <= surfelements.Size(); i++) + { + Element2d & el = SurfaceElement(i); + for (j = 0; j < el.GetNP(); j++) + el[j] = op2np[el[j]]; + } + + for (i = 0; i < segments.Size(); i++) + { + Segment & seg = segments[i]; + seg[0] = op2np[seg[0]]; + seg[1] = op2np[seg[1]]; + } + + for (i = 1; i <= openelements.Size(); i++) + { + Element2d & el = openelements.Elem(i); + for (j = 0; j < el.GetNP(); j++) + el[j] = op2np[el[j]]; + } + + + for (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; + } + + + CalcSurfacesOfNode(); + + + // FindOpenElements(); + timestamp = NextTimeStamp(); + + /* + (*testout) << "compress, done" << endl + << "np = " << points.Size() + << "ne = " << volelements.Size() << ", type.size = " << eltyps.Size() + << "volelements = " << volelements << endl; + */ + } + + + int Mesh :: CheckConsistentBoundary () const + { + int nf = GetNOpenElements(); + INDEX_2_HASHTABLE<int> 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 () + { + int i, j, k; + + Point3d pmin, pmax; + GetBox (pmin, pmax); + Box3dTree setree(pmin, pmax); + Array<int> 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<Mesh *>(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 -> Position(INDEX_2::Sort(el[i], el[j])); + if (pos) + { + be = true; + if (boundaryedges -> GetData(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<int> 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(); + } + } + + void Mesh :: BuildElementSearchTree () + { + if (elementsearchtreets == GetTimeStamp()) + return; + + NgLock lock(mutex); + lock.Lock(); + + PrintMessage (4, "Rebuild element searchtree"); + + delete elementsearchtree; + elementsearchtree = NULL; + + Box3d box; + int ne = (dimension == 2) ? GetNSE() : GetNE(); + if (!ne) + { + lock.UnLock(); + return; + } + + if (dimension == 2) + { + box.SetPoint (Point (SurfaceElement(1).PNum(1))); + for (int i = 1; i <= ne; i++) + { + const Element2d & el = SurfaceElement(i); + for (int j = 1; j <= el.GetNP(); j++) + box.AddPoint (Point (el.PNum(j))); + } + + box.Increase (1.01 * box.CalcDiam()); + elementsearchtree = new Box3dTree (box.PMin(), box.PMax()); + + for (int i = 1; i <= ne; i++) + { + const Element2d & el = SurfaceElement(i); + box.SetPoint (Point (el.PNum(1))); + for (int j = 1; j <= el.GetNP(); j++) + box.AddPoint (Point (el.PNum(j))); + + elementsearchtree -> Insert (box.PMin(), box.PMax(), i); + } + } + else + { + box.SetPoint (Point (VolumeElement(1).PNum(1))); + for (int i = 1; i <= ne; i++) + { + const Element & el = VolumeElement(i); + for (int j = 1; j <= el.GetNP(); j++) + box.AddPoint (Point (el.PNum(j))); + } + + box.Increase (1.01 * box.CalcDiam()); + elementsearchtree = new Box3dTree (box.PMin(), box.PMax()); + + for (int i = 1; i <= ne; i++) + { + const Element & el = VolumeElement(i); + box.SetPoint (Point (el.PNum(1))); + for (int j = 1; j <= el.GetNP(); j++) + box.AddPoint (Point (el.PNum(j))); + + elementsearchtree -> Insert (box.PMin(), box.PMax(), i); + } + } + + elementsearchtreets = GetTimeStamp(); + + lock.UnLock(); + } + + + + 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<Element2d> 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; + + double dxb = d.X()*b.Y()-d.Y()*b.X(); + double dxc = d.X()*c.Y()-d.Y()*c.X(); + 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; + lami[2]=0.; + double eps = 1.E-12; + + if(fabs(d.X()) <= eps && fabs(d.Y())<= eps) + { + //Solve Linear System + 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) + { + lami[1] = (dxp-dxa)/dxc; + if(fabs(b.X()-d.X()*lami[1])>=eps) + 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]); + } + else + if(fabs(dxc) <= eps) + { + lami[0] = (dxp-dxa)/dxb; + if(fabs(c.X()-d.X()*lami[0])>=eps) + 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]); + } + else //Solve quadratic equation + { + if(fabs(d.X()) >= eps) + { + c2 = d.X()*dxc; + c1 = d.X()*dxc - c.X()*dxb - d.X()*(dxp-dxa); + c0 = -b.X()*(dxp -dxa) - (a.X()-p.X())*dxb; + } + else + { + c2 = d.Y()*dxc; + c1 = d.Y()*dxc - c.Y()*dxb - d.Y()*(dxp-dxa); + c0 = -b.Y()*(dxp -dxa) - (a.Y()-p.Y())*dxb; + } + + double rt = c1*c1 - 4*c2*c0; + if (rt < 0.) return false; + lami[1] = (-c1 + sqrt(rt))/2/c2; + if(lami[1]<=1. && lami[1]>=0.) + { + lami[0] = (dxp - dxa -dxc*lami[1])/dxb; + if(lami[0]<=1. && lami[0]>=0.) + return true; + } + + lami[1] = (-c1 - sqrt(rt))/2/c2; + lami[0] = (dxp - dxa -dxc*lami[1])/dxb; + } + + 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 (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) + { + 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 && i<maxits) + { + curvedelems->CalcElementTransformation(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) + { + retval = (lam(0) > -eps && + lam(1) > -eps && + lam(2) > -eps && + lam(0) + lam(1) + lam(2) < 1+eps); + } + else if (el.GetType() == PRISM) + { + 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) + { + 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) + { + 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<Element> 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<Element> loctetsloc; + Array<netgen::Point<3> > 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 Point3d & p, + double lami[3], + bool build_searchtree, + const int index, + const bool allowindex) const + { + if(index != -1) + { + Array<int> 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 Point3d & p, + double lami[3], + const Array<int> * const indices, + bool build_searchtree, + const bool allowindex) const + { + if (dimension == 2) + { + int ne; + + + if(ps_startelement != 0 && ps_startelement <= GetNSE() && PointContainedIn2DElement(p,lami,ps_startelement)) + return ps_startelement; + + Array<int> locels; + if (elementsearchtree || build_searchtree) + { + // update if necessary: + const_cast<Mesh&>(*this).BuildElementSearchTree (); + 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 i, j; + int ne; + + if(ps_startelement != 0 && PointContainedIn3DElement(p,lami,ps_startelement)) + return ps_startelement; + + Array<int> locels; + if (elementsearchtree || build_searchtree) + { + // update if necessary: + const_cast<Mesh&>(*this).BuildElementSearchTree (); + 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 Point3d & p, + double lami[3], + bool build_searchtree, + const int index, + const bool allowindex) const + { + if(index != -1) + { + Array<int> 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 Point3d & p, + double lami[3], + const Array<int> * 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; + + Array<int> faces; + topology->GetElementFaces(velement,faces); + + //(*testout) << "faces " << faces << endl; + + for(int i=0; i<faces.Size(); i++) + faces[i] = topology->GetFace2SurfaceElement(faces[i]); + + //(*testout) << "surfel " << faces << endl; + + for(int i=0; i<faces.Size(); i++) + { + if(faces[i] == 0) + continue; + + if(indices && indices->Size() != 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]; + } + } + } + + } + + return 0; + } + + + void Mesh::GetIntersectingVolEls(const Point3d& p1, const Point3d& p2, + Array<int> & 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<SurfaceElementIndex> 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<SurfaceElementIndex> & 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; + 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; + int i; + + for (i = 1; i <= GetNE(); i++) + { + LegalTet (VolumeElement(i)); + + /* + Element & el = VolumeElement(i); + int leg1 = LegalTet (el); + el.flags.illegal_valid = 0; + int leg2 = LegalTet (el); + + if (leg1 != leg2) + { + cerr << "legal differs!!" << endl; + (*testout) << "legal differs" << endl; + (*testout) << "elnr = " << i << ", el = " << el + << " leg1 = " << leg1 << ", leg2 = " << leg2 << endl; + } + + // el.flags.illegal = !LegalTet (el); + */ + cnt += VolumeElement(i).Illegal(); + } + 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<int> & 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<INDEX_2> & 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 () + { + int i, j, nv; + int ne = GetNE(); + int nse = GetNSE(); + + numvertices = 0; + for (i = 1; i <= ne; i++) + { + const Element & el = VolumeElement(i); + nv = el.GetNV(); + for (j = 0; j < nv; j++) + if (el[j] > numvertices) + numvertices = el[j]; + } + for (i = 1; i <= nse; i++) + { + const Element2d & el = SurfaceElement(i); + nv = el.GetNV(); + for (j = 1; j <= nv; j++) + if (el.PNum(j) > numvertices) + numvertices = el.PNum(j); + } + + 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<int> 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<int> & 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() + { + topology->Update(); + clusters->Update(); + } + + + void Mesh :: SetMaterial (int domnr, const char * mat) + { + if (domnr > materials.Size()) + { + int olds = materials.Size(); + materials.SetSize (domnr); + for (int i = olds; i < domnr; i++) + materials[i] = 0; + } + materials.Elem(domnr) = new char[strlen(mat)+1]; + strcpy (materials.Elem(domnr), mat); + } + + const char * Mesh :: GetMaterial (int domnr) const + { + if (domnr <= materials.Size()) + return materials.Get(domnr); + return 0; + } + + 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 ( bcnames[bcnr] ) delete bcnames[bcnr]; + if ( abcname != "default" ) + bcnames[bcnr] = new string ( abcname ); + else + bcnames[bcnr] = 0; + } + + string Mesh ::GetBCName ( int bcnr ) const + { + if ( !bcnames.Size() ) + return "default"; + if ( bcnames[bcnr] ) + return *bcnames[bcnr]; + else + return "default"; + } + + void Mesh :: SetUserData(const char * id, Array<int> & data) + { + if(userdata_int.Used(id)) + delete userdata_int.Get(id); + + Array<int> * newdata = new Array<int>(data); + + userdata_int.Set(id,newdata); + } + bool Mesh :: GetUserData(const char * id, Array<int> & data, int shift) const + { + if(userdata_int.Used(id)) + { + if(data.Size() < (*userdata_int.Get(id)).Size()+shift) + data.SetSize((*userdata_int.Get(id)).Size()+shift); + for(int i=0; i<(*userdata_int.Get(id)).Size(); i++) + data[i+shift] = (*userdata_int.Get(id))[i]; + return true; + } + else + { + data.SetSize(0); + return false; + } + } + void Mesh :: SetUserData(const char * id, Array<double> & data) + { + if(userdata_double.Used(id)) + delete userdata_double.Get(id); + + Array<double> * newdata = new Array<double>(data); + + userdata_double.Set(id,newdata); + } + bool Mesh :: GetUserData(const char * id, Array<double> & data, int shift) const + { + if(userdata_double.Used(id)) + { + if(data.Size() < (*userdata_double.Get(id)).Size()+shift) + data.SetSize((*userdata_double.Get(id)).Size()+shift); + for(int i=0; i<(*userdata_double.Get(id)).Size(); i++) + data[i+shift] = (*userdata_double.Get(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); + } +} diff --git a/contrib/Netgen/libsrc/meshing/meshclass.hpp b/contrib/Netgen/libsrc/meshing/meshclass.hpp new file mode 100644 index 0000000000..1f45d1f0ec --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshclass.hpp @@ -0,0 +1,770 @@ +#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 MoveableArray<MeshPoint,PointIndex::BASE> T_POINTS; + // typedef MoveableArray<Element> T_VOLELEMENTS; + // typedef MoveableArray<Element2d> T_SURFELEMENTS; + + // typedef Array<MeshPoint,PointIndex::BASE> T_POINTS; + typedef Array<Element> T_VOLELEMENTS; + typedef Array<Element2d> T_SURFELEMENTS; + + + private: + /// point coordinates + T_POINTS points; + + /// line-segments at edges + Array<Segment> segments; + /// surface elements, 2d-inner elements + T_SURFELEMENTS surfelements; + /// volume elements + T_VOLELEMENTS volelements; + /// points will be fixed forever + Array<PointIndex> lockedpoints; + + + /// surface indices at boundary nodes + TABLE<int,PointIndex::BASE> surfacesonnode; + /// boundary edges (1..normal bedge, 2..segment) + INDEX_2_CLOSED_HASHTABLE<int> * boundaryedges; + /// + INDEX_2_CLOSED_HASHTABLE<int> * segmentht; + /// + INDEX_3_CLOSED_HASHTABLE<int> * surfelementht; + + /// faces of rest-solid + Array<Element2d> openelements; + /// open segmenets for surface meshing + Array<Segment> opensegments; + + + + /** + Representation of local mesh-size h + */ + LocalH * lochfunc; + /// + double hglob; + /// + double hmin; + /// + Array<double> maxhdomain; + + /** + the face-index of the surface element maps into + this table. + */ + Array<FaceDescriptor> facedecoding; + + + /** + the edge-index of the line element maps into + this table. + */ + Array<EdgeDescriptor> edgedecoding; + + /// sub-domain materials + Array<char*> materials; + + /// labels for boundary conditions + Array<string*> bcnames; + + /// Periodic surface, close surface, etc. identifications + Identifications * ident; + + + /// number of vertices (if < 0, use np) + int numvertices; + + /// geometric search tree for interval intersection search + Box3dTree * elementsearchtree; + /// time stamp for tree + int elementsearchtreets; + + /// element -> face, element -> edge etc ... + class 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<int>* > userdata_int; + SYMBOLTABLE< Array<double>* > userdata_double; + + + mutable Array< Point3d > pointcurves; + mutable Array<int> pointcurves_startpoint; + mutable Array<double> 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 + + + 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<HPRefElement> * hpelements; + Mesh * coarsemesh; + + + /// number of refinement levels + int mglevels; + /// refinement hierarchy + Array<INDEX_2,PointIndex::BASE> mlbetweennodes; + /// parent element of volume element + Array<int> mlparentelement; + /// parent element of surface element + Array<int> mlparentsurfaceelement; + + + + /// + DLL_HEADER Mesh(); + /// + DLL_HEADER ~Mesh(); + + Mesh & operator= (const Mesh & mesh2); + + /// + DLL_HEADER void DeleteMesh(); + + /// + void ClearSurfaceElements(); + + /// + void ClearVolumeElements() + { + volelements.SetSize(0); + timestamp = NextTimeStamp(); + } + + /// + 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); +#ifdef PARALLEL + PointIndex AddPoint (const Point3d & p, bool aisghost, int layer = 1); + PointIndex AddPoint (const Point3d & p, bool aisghost, int layer, POINTTYPE type); +#endif + int GetNP () const { return points.Size(); } + + MeshPoint & Point(int i) { return points.Elem(i); } + MeshPoint & Point(PointIndex pi) { return points[pi]; } + 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] = PointIndex::BASE-1; + segments.Elem(segnr)[1] = PointIndex::BASE-1; + } + void FullDeleteSegment (int segnr) // von wem ist das ??? + { + segments.Delete(segnr-PointIndex::BASE); + } + + int GetNSeg () const { return segments.Size(); } + Segment & LineSegment(int i) { return segments.Elem(i); } + 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]; } + + + + + DLL_HEADER SurfaceElementIndex AddSurfaceElement (const Element2d & el); + void DeleteSurfaceElement (int eli) + { + surfelements.Elem(eli).Delete(); + surfelements.Elem(eli).PNum(1) = -1; + surfelements.Elem(eli).PNum(2) = -1; + surfelements.Elem(eli).PNum(3) = -1; + timestamp = NextTimeStamp(); + } + + void DeleteSurfaceElement (SurfaceElementIndex eli) + { + DeleteSurfaceElement (int(eli)+1); + } + + int GetNSE () const { return surfelements.Size(); } + Element2d & SurfaceElement(int i) { return surfelements.Elem(i); } + 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]; } + + + DLL_HEADER void RebuildSurfaceElementLists (); + DLL_HEADER void GetSurfaceElementsOfFace (int facenr, Array<SurfaceElementIndex> & sei) const; + + DLL_HEADER ElementIndex AddVolumeElement (const Element & el); + + int GetNE () const { return volelements.Size(); } + + Element & VolumeElement(int i) { return volelements.Elem(i); } + 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 T_VOLELEMENTS & VolumeElements() const { return volelements; } + T_VOLELEMENTS & VolumeElements() { return volelements; } + + + /// + DLL_HEADER double ElementError (int eli, const MeshingParameters & mp) const; + + /// + DLL_HEADER void AddLockedPoint (PointIndex pi); + /// + void ClearLockedPoints (); + + const Array<PointIndex> & LockedPoints() const + { return lockedpoints; } + + /// Returns number of domains + int GetNDomains() const; + + /// + int GetDimension() const + { return dimension; } + void SetDimension(int dim) + { dimension = dim; } + + /// sets internal tables + 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 (const Point3d & pmin, const Point3d & 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 char * meshsizefilename); + /// + DLL_HEADER void SetGlobalH (double h); + /// + void SetMinimalH (double h); + /// + double MaxHDomain (int dom) const; + /// + void SetMaxHDomain (const Array<double> & mhd); + /// + double GetH (const Point3d & p) const; + /// + double GetMinH (const Point3d & pmin, const Point3d & pmax); + /// + 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); } + + + /// are also quads open elements + bool HasOpenQuads () const; + + /// split into connected pieces + void SplitIntoParts (); + + /// + 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<Mesh *>(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 (); + + /// + void Save (ostream & outfile) const; + /// + void Load (istream & infile); + /// + void Merge (istream & infile, const int surfindex_offset = 0); + /// + void Save (const string & filename) const; + /// + void Load (const string & filename); + /// + void Merge (const string & filename, const int surfindex_offset = 0); + + + /// + 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<int,PointIndex::BASE>* > * 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 + */ + void CalcMinMaxAngle (double badellimit, double * retvalues = NULL); + + /* + Marks elements which are dangerous to refine + return: number of illegal elements + */ + int MarkIllegalElements (); + + /// orient surface mesh, for one sub-domain only + void SurfaceMeshOrientation (); + + /// convert mixed element mesh to tet-mesh + 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 Point3d & p, + double * lami, + bool build_searchtree = 0, + const int index = -1, + const bool allowindex = true) const; + int GetElementOfPoint (const Point3d & p, + double * lami, + const Array<int> * const indices, + bool build_searchtree = 0, + const bool allowindex = true) const; + int GetSurfaceElementOfPoint (const Point3d & p, + double * lami, + bool build_searchtree = 0, + const int index = -1, + const bool allowindex = true) const; + int GetSurfaceElementOfPoint (const Point3d & p, + double * lami, + const Array<int> * 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<int> & locels) const; + + /// + int AddFaceDescriptor(const FaceDescriptor& fd) + { return facedecoding.Append(fd); } + + int AddEdgeDescriptor(const EdgeDescriptor & fd) + { return edgedecoding.Append(fd) - 1; } + + /// + DLL_HEADER void SetMaterial (int domnr, const char * mat); + /// + const char * GetMaterial (int domnr) const; + + DLL_HEADER void SetNBCNames ( int nbcn ); + + DLL_HEADER void SetBCName ( int bcnr, const string & abcname ); + + string GetBCName ( int bcnr ) const; + + string * GetBCNamePtr ( int bcnr ) + { return bcnames[bcnr]; } + + /// + 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<int> & GetIdentifiedPoints () + // { + // return *identifiedpoints; + // } + + // /// + // void GetIdentificationMap (int identnr, Array<int> & identmap) const; + // /// + // void GetIdentificationPairs (int identnr, Array<INDEX_2> & 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; } + + + 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); + + + + + /* + /// build connected nodes along prism stack + void BuildConnectedNodes (); + void ConnectToNodeRec (int node, int tonode, + const TABLE<int> & conto); + */ + + bool PureTrigMesh (int faceindex = 0) const; + bool PureTetMesh () const; + + + const class MeshTopology & GetTopology () const + { return *topology; } + + void UpdateTopology(); + + class CurvedElements & GetCurvedElements () const + { return *curvedelems; } + + const class AnisotropicClusters & GetClusters () const + { return *clusters; } + + 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; } + + + /// + void SetUserData(const char * id, Array<int> & data); + /// + bool GetUserData(const char * id, Array<int> & data, int shift = 0) const; + /// + void SetUserData(const char * id, Array<double> & data); + /// + bool GetUserData(const char * id, Array<double> & 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 (); + + + /// find connection to parallel meshes + // void FindExchangePoints () ; + + // void FindExchangeEdges (); + // void FindExchangeFaces (); + + /// use metis to decompose master mesh + void ParallelMetis (); // Array<int> & neloc ); + void PartHybridMesh (); // Array<int> & neloc ); + void PartDualHybridMesh (); // Array<int> & neloc ); + void PartDualHybridMesh2D (); // ( Array<int> & 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<int> & neloc) const; + /// loads a mesh sent from master processor + void ReceiveParallelMesh (); + + + void UpdateOverlap (); + +#endif + + + }; + + inline ostream& operator<<(ostream& ost, const Mesh& mesh) + { + ost << "mesh: " << endl; + mesh.Save(ost); + return ost; + } + +} + +#endif + + diff --git a/contrib/Netgen/libsrc/meshing/meshfunc.cpp b/contrib/Netgen/libsrc/meshing/meshfunc.cpp new file mode 100644 index 0000000000..9dbc8a8ca9 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshfunc.cpp @@ -0,0 +1,717 @@ +#include <mystdlib.h> +#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 double teterrpow; + MESHING3_RESULT MeshVolume (MeshingParameters & mp, Mesh& mesh3d) + { + int oldne; + int meshed; + + Array<INDEX_2> connectednodes; + + if (&mesh3d.LocalHFunction() == NULL) 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++) + { + 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 (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 = 1; qstep <= 3; qstep++) + { + // cout << "openquads = " << mesh3d.HasOpenQuads() << endl; + if (mesh3d.HasOpenQuads()) + { + string rulefile = ngdir; + + const char ** rulep = NULL; + switch (qstep) + { + 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 = PointIndex::BASE; + pi < mesh3d.GetNP()+PointIndex::BASE; 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 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 = PointIndex::BASE; + pi < mesh3d.GetNP()+PointIndex::BASE; pi++) + 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<int, PointIndex::BASE> glob2loc(mesh3d.GetNP()); + glob2loc = -1; + + for (PointIndex pi = PointIndex::BASE; + pi < mesh3d.GetNP()+PointIndex::BASE; 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 elemetns: ", 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) + { + 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++) + { + 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) + { + 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"); + } +} diff --git a/contrib/Netgen/libsrc/meshing/meshfunc.hpp b/contrib/Netgen/libsrc/meshing/meshfunc.hpp new file mode 100644 index 0000000000..f39c0a8fcb --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshfunc.hpp @@ -0,0 +1,41 @@ +#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 +MESHING3_RESULT MeshVolume (MeshingParameters & mp, Mesh& mesh3d); + +/// Build mixed-element mesh +// MESHING3_RESULT MeshMixedVolume (MeshingParameters & mp, Mesh& mesh3d); + +/// Optimize tet-mesh +MESHING3_RESULT OptimizeVolume (MeshingParameters & mp, Mesh& mesh3d); +// const CSGeometry * geometry = NULL); + +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 diff --git a/contrib/Netgen/libsrc/meshing/meshfunc2d.cpp b/contrib/Netgen/libsrc/meshing/meshfunc2d.cpp new file mode 100644 index 0000000000..495f877760 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshfunc2d.cpp @@ -0,0 +1,61 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + + DLL_HEADER void Optimize2d (Mesh & mesh, MeshingParameters & mp) + { + int i; + + //double h = mp.maxh; + + mesh.CalcSurfacesOfNode(); + + const char * optstr = mp.optimize2d; + int optsteps = mp.optsteps2d; + + // cout << "optstr = " << optstr << endl; + + for (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 (0); + meshopt.EdgeSwapping (mesh, 0); + break; + } + case 'S': + { // metric swap + MeshOptimize2d meshopt; + meshopt.SetMetricWeight (0); + meshopt.EdgeSwapping (mesh, 1); + break; + } + case 'm': + { + MeshOptimize2d meshopt; + meshopt.SetMetricWeight (1); + meshopt.ImproveMesh(mesh, mp); + break; + } + + case 'c': + { + MeshOptimize2d meshopt; + meshopt.SetMetricWeight (0.2); + meshopt.CombineImprove(mesh); + break; + } + default: + cerr << "Optimization code " << optstr[j-1] << " not defined" << endl; + } + } + } + +} diff --git a/contrib/Netgen/libsrc/meshing/meshing.hpp b/contrib/Netgen/libsrc/meshing/meshing.hpp new file mode 100644 index 0000000000..7fd9c19632 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshing.hpp @@ -0,0 +1,71 @@ +#ifndef FILE_MESHING +#define FILE_MESHING + + + +#include "../include/myadt.hpp" +#include "../include/gprim.hpp" +#include "../include/linalg.hpp" +#include "../include/opti.hpp" + + + +namespace netgen +{ + // extern int printmessage_importance; + + class CSGeometry; + class NetgenGeometry; +} + + +#include "msghandler.hpp" +#include "meshtype.hpp" +#include "localh.hpp" +#include "meshclass.hpp" +#include "global.hpp" + + +namespace netgen +{ +#include "meshtool.hpp" +#include "ruler2.hpp" +#include "adfront2.hpp" +#include "meshing2.hpp" +#include "improve2.hpp" + + +#include "geomsearch.hpp" +#include "adfront3.hpp" +#include "ruler3.hpp" + +#define _INCLUDE_MORE + + +#include "meshing3.hpp" +#include "improve3.hpp" + +#include "findip.hpp" +#include "findip2.hpp" + +#include "topology.hpp" +#include "curvedelems.hpp" +#include "clusters.hpp" + +#include "meshfunc.hpp" + +#include "bisect.hpp" +#include "hprefinement.hpp" +#include "boundarylayer.hpp" +#include "specials.hpp" +} + +#include "validate.hpp" +#include "basegeom.hpp" + +#ifdef PARALLEL +#include "paralleltop.hpp" +#endif + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/meshing2.cpp b/contrib/Netgen/libsrc/meshing/meshing2.cpp new file mode 100644 index 0000000000..d31c73e1d5 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshing2.cpp @@ -0,0 +1,1957 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + static void glrender (int wait); + + + // global variable for visualization +// static Array<Point3d> locpoints; +// static Array<int> legalpoints; +// static Array<Point2d> plainpoints; +// static Array<int> plainzones; +// static Array<INDEX_2> 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<Point2d> & points, + Array<Point3d> & points3d, + Array<INDEX_2> & 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 int timer = NgProfiler::CreateTimer ("surface meshing"); + + static int timer1 = NgProfiler::CreateTimer ("surface meshing1"); + static int timer2 = NgProfiler::CreateTimer ("surface meshing2"); + static int timer3 = NgProfiler::CreateTimer ("surface meshing3"); + NgProfiler::RegionTimer reg (timer); + + + Array<int> pindex, lindex; + Array<int> delpoints, dellines; + + Array<PointGeomInfo> upgeominfo; // unique info + Array<MultiPointGeomInfo> mpgeominfo; // multiple info + + Array<Element2d> locelements; + + int z1, z2, oldnp(-1); + bool found; + int rulenr(-1); + int globind; + Point<3> p1, p2; + + const PointGeomInfo * blgeominfo1; + const PointGeomInfo * blgeominfo2; + + bool morerisc; + bool debugflag; + + double h, his, hshould; + + + Array<Point3d> locpoints; + Array<int> legalpoints; + Array<Point2d> plainpoints; + Array<int> plainzones; + Array<INDEX_2> loclines; + int cntelem = 0, trials = 0, nfaces = 0; + int oldnl = 0; + int qualclass; + + + + // test for 3d overlaps + Box3dTree surfeltree (boundingbox.PMin(), + boundingbox.PMax()); + + Array<int> intersecttrias; + Array<Point3d> critpoints; + + // test for doubled edges + //INDEX_2_HASHTABLE<int> doubleedge(300000); + + + testmode = 0; + + StartMesh(); + + Array<Point2d> chartboundpoints; + Array<Point3d> chartboundpoints3d; + Array<INDEX_2> chartboundlines; + + // illegal points: points with more then 50 elements per node + int maxlegalpoint(-1), maxlegalline(-1); + Array<int,PointIndex::BASE> trigsonnode; + Array<int,PointIndex::BASE> 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<SurfaceElementIndex> 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, i); + } + + + + + if (totalarea > 0 || maxarea > 0) + 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; + } + + + + + const char * savetask = multithread.task; + multithread.task = "Surface meshing"; + + adfront ->SetStartFront (); + + + int plotnexttrial = 999; + + double meshedarea_before = meshedarea; + + + 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 (j = 1; j <= mesh.GetNSE(); j++) + { + */ + int jj; + for (jj = 1; jj <= intersecttrias.Size(); jj++) + { + int j = intersecttrias.Get(jj); + const Element2d & el = mesh.SurfaceElement(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++) + { + 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()); + + 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 <visual.hpp> +#include <stlgeom.hpp> + +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 diff --git a/contrib/Netgen/libsrc/meshing/meshing2.hpp b/contrib/Netgen/libsrc/meshing/meshing2.hpp new file mode 100644 index 0000000000..4e14596438 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshing2.hpp @@ -0,0 +1,164 @@ +#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<netrule*> rules; + /// statistics + Array<int> 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<Point2d> & points, + Array<Point3d> & points3d, + Array<INDEX_2> & lines, double p) const; + + virtual double Area () const; + + +/** Applies 2D rules. + Tests all 2D rules */ + int ApplyRules (Array<Point2d> & lpoints, + Array<int> & legalpoints, + int maxlegalpoint, + Array<INDEX_2> & llines, + int maxlegelline, + Array<Element2d> & elements, Array<INDEX> & dellines, + int tolerance, + const MeshingParameters & mp); + + +}; + + + + + + + + +#endif + + + + + + + diff --git a/contrib/Netgen/libsrc/meshing/meshing3.cpp b/contrib/Netgen/libsrc/meshing/meshing3.cpp new file mode 100644 index 0000000000..3421c3192c --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshing3.cpp @@ -0,0 +1,1264 @@ +#include <mystdlib.h> +#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]; + } +} + + + +static double CalcLocH (const Array<Point3d> & locpoints, + const Array<MiniElement2d> & locfaces, + double h) +{ + return h; + + // was war das ???? + + 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 (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 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<Point3d > locpoints; // local points + Array<MiniElement2d> locfaces; // local faces + Array<PointIndex> pindex; // mapping from local to front point numbering + Array<int> allowpoint; // point is allowd ? + Array<INDEX> findex; // mapping from local to front face numbering + //INDEX_2_HASHTABLE<int> connectedpairs(100); // connecgted pairs for prism meshing + + Array<Point3d > plainpoints; // points in reference coordinates + Array<int> delpoints, delfaces; // points and lines to be deleted + Array<Element> locelements; // new generated elements + + int i, j, oldnp, oldnf; + int found; + referencetransform trans; + int rotind; + INDEX globind; + 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<MeshPoint> grouppoints; + Array<MiniElement2d> groupfaces; + Array<PointIndex> grouppindex; + Array<INDEX> groupfindex; + + + float minerr; + int hasfound; + double tetvol; + // int giveup = 0; + + + Array<Point3d> tempnewpoints; + Array<MiniElement2d> tempnewfaces; + Array<int> tempdelfaces; + Array<Element> 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<int> 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 Point3d & p1 = adfront->GetPoint (bel.PNum(1)); + const Point3d & p2 = adfront->GetPoint (bel.PNum(2)); + const Point3d & p3 = adfront->GetPoint (bel.PNum(3)); + + // (*testout) << endl << "base = " << bel << endl; + + + Point3d pmid = Center (p1, p2, p3); + + double his = (Dist (p1, p2) + Dist(p1, p3) + Dist(p2, p3)) / 3; + double hshould; + + 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); + + NgProfiler::StartTimer (meshing3_timer_a); + stat.qualclass = + adfront -> GetLocals (baseelem, locpoints, locfaces, + pindex, findex, connectedpairs, + houter, hinner, + locfacesplit); + NgProfiler::StopTimer (meshing3_timer_a); + + // (*testout) << "locfaces = " << endl << locfaces << endl; + + int pi1 = pindex.Get(locfaces[0].PNum(1)); + int pi2 = pindex.Get(locfaces[0].PNum(2)); + int pi3 = pindex.Get(locfaces[0].PNum(3)); + + //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; + (*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 (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 (i = 0; i < groupfaces.Size(); i++) + 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 (i = 1; i <= groupfaces.Size(); i++) + adfront -> DeleteFace (groupfindex.Get(i)); + + for (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; + + npi = mesh.AddPoint (inp); + newel.SetNP(4); + newel.PNum(4) = npi; + + for (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 (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 (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.Get(1).GetNP() == 3) + { + trans.Set (locpoints.Get(locfaces.Get(1).PNumMod(1+rotind)), + locpoints.Get(locfaces.Get(1).PNumMod(2+rotind)), + locpoints.Get(locfaces.Get(1).PNumMod(3+rotind)), hshould); + } + else + { + trans.Set (locpoints.Get(locfaces.Get(1).PNumMod(1+rotind)), + locpoints.Get(locfaces.Get(1).PNumMod(2+rotind)), + locpoints.Get(locfaces.Get(1).PNumMod(4+rotind)), hshould); + } + + trans.ToPlain (locpoints, plainpoints); + + + for (i = 1; i <= allowpoint.Size(); i++) + { + if (plainpoints.Get(i).Z() > 0) + { + //if(loktestmode) + // (*testout) << "plainpoints.Get(i).Z() = " << plainpoints.Get(i).Z() << " > 0" << endl; + allowpoint.Elem(i) = 0; + } + } + + stat.cnttrials++; + + + if (stat.cnttrials % 100 == 0) + { + (*testout) << "\n"; + for (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); + + 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; + + + 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 (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 (i = 1; i <= locelements.Size(); i++) + { + Point3d pmin = locpoints.Get(locelements.Get(i).PNum(1)); + Point3d pmax = pmin; + for (j = 2; j <= 4; j++) + { + const Point3d & hp = locpoints.Get(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 (i = 1; i <= locelements.Size(); i++) + for (j = 1; j <= 4; j++) + { + const Point3d & hp = locpoints.Get(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 (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 (i = oldnp+1; i <= locpoints.Size(); i++) + tempnewpoints.Append (locpoints.Get(i)); + + tempnewfaces.SetSize (0); + for (i = oldnf+1; i <= locfaces.Size(); i++) + tempnewfaces.Append (locfaces.Get(i)); + + tempdelfaces.SetSize (0); + for (i = 1; i <= delfaces.Size(); i++) + tempdelfaces.Append (delfaces.Get(i)); + + templocelements.SetSize (0); + for (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 (i = 1; i <= tempnewpoints.Size(); i++) + locpoints.Append (tempnewpoints.Get(i)); + for (i = 1; i <= tempnewfaces.Size(); i++) + locfaces.Append (tempnewfaces.Get(i)); + for (i = 1; i <= tempdelfaces.Size(); i++) + delfaces.Append (tempdelfaces.Get(i)); + for (i = 1; i <= templocelements.Size(); i++) + locelements.Append (templocelements.Get(i)); + + + if (loktestmode) + { + (*testout) << "apply rule" << endl; + for (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 (i = oldnp+1; i <= locpoints.Size(); i++) + { + globind = mesh.AddPoint (locpoints.Get(i)); + pindex.Elem(i) = adfront -> AddPoint (locpoints.Get(i), globind); + } + + for (i = 1; i <= locelements.Size(); i++) + { + Point3d * hp1, * hp2, * hp3, * hp4; + hp1 = &locpoints.Elem(locelements.Get(i).PNum(1)); + hp2 = &locpoints.Elem(locelements.Get(i).PNum(2)); + hp3 = &locpoints.Elem(locelements.Get(i).PNum(3)); + hp4 = &locpoints.Elem(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.Get(locelements.Get(i).PNum(j))); + + mesh.AddVolumeElement (locelements.Get(i)); + stat.cntelem++; + } + + for (i = oldnf+1; i <= locfaces.Size(); i++) + { + for (j = 1; j <= locfaces.Get(i).GetNP(); j++) + locfaces.Elem(i).PNum(j) = + pindex.Get(locfaces.Get(i).PNum(j)); + // (*testout) << "add face " << locfaces.Get(i) << endl; + adfront->AddFace (locfaces.Get(i)); + } + + for (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 (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) +{ + 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 (i = 1; i <= adfront->GetNP(); i++) + { + const Point3d & p = adfront->GetPoint(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<blocktyp> inner(n); + Array<int> pointnr(n), frontpointnr(n); + + + // initialize inner to 1 + + for (i = 1; i <= n; i++) + inner.Elem(i) = BLOCKUNDEF; + + + // set blocks cutting surfaces to 0 + + for (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 (i = 1; i <= n; i++) + if (inner.Elem(i) == BLOCKINNER) + { + filled++; + } + PrintMessage (5, "Filled blocks: ", filled); + + for (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) +{ + double filldist = mp.filldist; + + (*testout) << "blockfill local h" << endl; + (*testout) << "rel filldist = " << filldist << endl; + PrintMessage (3, "blockfill local h"); + + + Array<Point<3> > 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))) + { + int 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))) + { + int gpnum = mesh.AddPoint (npoints.Get(i)); + adfront->AddPoint (npoints.Get(i), gpnum); + } + } +} + +} diff --git a/contrib/Netgen/libsrc/meshing/meshing3.hpp b/contrib/Netgen/libsrc/meshing/meshing3.hpp new file mode 100644 index 0000000000..84e9ca6b71 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshing3.hpp @@ -0,0 +1,130 @@ +#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<vnetrule*> rules; + /// counts how often a rule is used + Array<int> ruleused, canuse, foundmap; + /// describes, why a rule is not applied + Array<char*> 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<Point3d> & lpoints, Array<int> & allowpoint, + Array<MiniElement2d> & lfaces, INDEX lfacesplit, + INDEX_2_HASHTABLE<int> & connectedpairs, + Array<Element> & elements, + Array<INDEX> & 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 <typename POINTArray, typename FACEArray> +extern int FindInnerPoint (POINTArray & grouppoints, + FACEArray & groupfaces, + Point3d & p); + +*/ + + + + + +#endif + + + + + + + + + + diff --git a/contrib/Netgen/libsrc/meshing/meshtool.cpp b/contrib/Netgen/libsrc/meshing/meshtool.cpp new file mode 100644 index 0000000000..4a349ac9c4 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshtool.cpp @@ -0,0 +1,1015 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#include <csg.hpp> +#include <geometry2d.hpp> + +namespace netgen +{ + + int CheckSurfaceMesh (const Mesh & mesh) + { + PrintMessage (3, "Check Surface mesh"); + + int nf = mesh.GetNSE(); + INDEX_2_HASHTABLE<int> 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<INDEX> 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; + } + + if (teterrpow == 2) + { + errpow = err*err; + grad = (2 * err) * graderr; + } + + if(teterrpow > 2) + { + 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<Point3d> & 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<Point3d> & points, + const Array<Element> & 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<int> * inclass) + { + int ncl = 20; + signed int cl; + Array<INDEX> 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<SplineSegment *> * 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 CSGeometry & 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<int> 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<PointIndex::BASE> 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()); + } + +} diff --git a/contrib/Netgen/libsrc/meshing/meshtool.hpp b/contrib/Netgen/libsrc/meshing/meshtool.hpp new file mode 100644 index 0000000000..b6472ce080 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshtool.hpp @@ -0,0 +1,81 @@ +#ifndef FILE_MESHTOOL +#define FILE_MESHTOOL + + +/// +extern void MeshQuality2d (const Mesh & mesh); + +/// +extern void MeshQuality3d (const Mesh & mesh, + Array<int> * 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<class SplineSegment*> * splines, + ostream & outfile); +*/ + +class Surface; +/// +extern void SaveVolumeMesh ( + const Array<Point3d> & points, + const Array<Element> & elements, + const Array<Element> & volelements, + const Array<Surface*> & surfaces, + char * filename); + +/// +void SaveVolumeMesh (const Mesh & mesh, + const class CSGeometry & 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<Point3d> & 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<Point3d> & points, + const Array<Element> & 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 diff --git a/contrib/Netgen/libsrc/meshing/meshtype.cpp b/contrib/Netgen/libsrc/meshing/meshtype.cpp new file mode 100644 index 0000000000..8bdbe8cb38 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshtype.cpp @@ -0,0 +1,2680 @@ +#include <mystdlib.h> + +#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() + { + 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 = 0; + } + + 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), + 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; + } + + return *this; + } + + + 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; +#ifdef PARALLEL + isghost = 0; +#endif + } + + + 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; +#ifdef PARALLEL + isghost = 0; +#endif + } + + 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; +#ifdef PARALLEL + isghost = 0; +#endif + + } + + + + 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; + +#ifdef PARALLEL + isghost = 0; +#endif + + } + + 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; + +#ifdef PARALLEL + isghost = 0; +#endif + } + + + /* + 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<np; i++) + retval = (el2[i] == (*this)[i]); + + return retval; + } + + + void Element2d :: Invert2() + { + switch (typ) + { + case TRIG: + { + Swap (pnum[1], pnum[2]); + break; + } + case TRIG6: + { + Swap (pnum[1], pnum[2]); + Swap (pnum[4], pnum[5]); + break; + } + case QUAD: + { + Swap (pnum[0], pnum[3]); + Swap (pnum[1], pnum[2]); + break; + } + default: + { + cerr << "Element2d::Invert2, illegal element type " << int(typ) << endl; + } + } + } + + int Element2d::HasFace(const Element2d & el) const + { + //nur für tets!!! hannes + for (int i = 1; i <= 3; i++) + { + if (PNumMod(i) == el[0] && + PNumMod(i+1) == el[1] && + PNumMod(i+2) == el[2]) + { + return 1; + } + } + return 0; + } + + void Element2d :: NormalizeNumbering2 () + { + 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 + { + int mini = 1; + for (int i = 2; i <= GetNP(); i++) + if (PNum(i) < PNum(mini)) mini = i; + + Element2d hel = (*this); + for (int i = 1; i <= GetNP(); i++) + PNum(i) = hel.PNumMod (i+mini-1); + } + } + + + + + Array<IntegrationPointData*> ipdtrig; + Array<IntegrationPointData*> 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 ", typ); + } + + p.X() = pp[0]; + p.Y() = pp[1]; + weight = pp[2]; + } + + void Element2d :: + GetTransformation (int ip, const Array<Point2d> & 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 ", 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 ", 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; + } + } + } + + + + + + + + + + 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 ", typ); + } + } + + + + void Element2d :: + GetDShapeNew (const Point<2> & p, MatrixFixWidth<2> & dshape) const + { + switch (typ) + { + case TRIG: + { + dshape = 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; + } + } + } + + + + + + void Element2d :: + GetPointMatrix (const Array<Point2d> & 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<Point2d> & 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<Point2d> & 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 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; + +#ifdef PARALLEL + partitionNumber = -1; + isghost = 0; +#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; + default: cerr << "Element::Element: unknown element with " << np << " points" << endl; + } + orderx = ordery = orderz = 1; + +#ifdef PARALLEL + isghost = 0; +#endif + } + + 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; + +#ifdef PARALLEL + isghost = 0; +#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; + 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; + // + 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 PRISM12: np = 12; break; + + default: break; + cerr << "Element::SetType unknown type " << int(typ) << endl; + } + } + + + + 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 } + }; + + 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; + } + } + } + + + + void Element :: GetTets (Array<Element> & 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<Element> & 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<np; i++) + retval = (el2[i] == (*this)[i]); + + return retval; + } + + +#ifdef OLD + void Element :: GetNodesLocal (Array<Point3d> & 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<Point<3> > & 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<Element2d> & 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< AutoPtr < IntegrationPointData > > ipdtet; + Array< AutoPtr < 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; + } + + 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; + } + } + } + + + + void Element :: GetShapeNew (const Point<3> & p, FlatVector & 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: + { + double lam1 = p(0); + double lam2 = p(1); + double lam3 = p(2); + double 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: + { + double noz = 1-p(2); + if (noz == 0.0) noz = 1e-10; + + double xi = p(0) / noz; + double 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 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 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; + } + } + } + + + + 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); + } + } + + + void Element :: + GetDShapeNew (const Point<3> & p, MatrixFixWidth<3> & dshape) const + { + switch (typ) + { + case TET: + { + dshape = 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 = 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; + 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; + + GetShapeNew (pr, shaper); + GetShapeNew (pl, shapel); + for (int j = 0; j < np; j++) + dshape(j, i-1) = (shaper(j) - shapel(j)) / (2 * eps); + } + } + } + } + + 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 :: GetBCName () const + { + if ( bcname ) + return *bcname; + else + return "default"; + + } + + /* + void FaceDescriptor :: SetBCName (string * bcn) + { + bcname = bcn; + } + */ + + + ostream & operator<<(ostream & s, const FaceDescriptor & fd) + { + s << "surfnr = " << fd.SurfNr() + << ", domin = " << fd.DomainIn() + << ", domout = " << fd.DomainOut() + << ", tlosurf = " << fd.TLOSurface() + << ", bcprop = " << fd.BCProperty() + << ", domin_sing = " << fd.DomainInSingular() + << ", domout_sing = " << fd.DomainOutSingular() + << ", colour = " << fd.SurfColour(); + return s; + } + + + + + + + Identifications :: Identifications (Mesh & amesh) + : mesh(amesh) + { + identifiedpoints = new INDEX_2_HASHTABLE<int>(100); + identifiedpoints_nr = new INDEX_3_HASHTABLE<int>(100); + maxidentnr = 0; + } + + Identifications :: ~Identifications () + { + delete identifiedpoints; + delete identifiedpoints_nr; + } + + void Identifications :: Delete () + { + delete identifiedpoints; + identifiedpoints = new INDEX_2_HASHTABLE<int>(100); + delete identifiedpoints_nr; + identifiedpoints_nr = new INDEX_3_HASHTABLE<int>(100); + maxidentnr = 0; + } + + 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<int,PointIndex::BASE> & 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<INDEX_2> & 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; + if(meshsizefilename) + ost << " meshsizefilename = " << meshsizefilename << endl; + else + ost << " meshsizefilename = NULL" << endl; + ost << " 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<char*>(meshsizefilename), other.meshsizefilename); + //const_cast<char*>(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; + }; + + + +} + diff --git a/contrib/Netgen/libsrc/meshing/meshtype.hpp b/contrib/Netgen/libsrc/meshing/meshtype.hpp new file mode 100644 index 0000000000..c7b3609ded --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshtype.hpp @@ -0,0 +1,1306 @@ +#ifndef MESHTYPE +#define MESHTYPE + + +/**************************************************************************/ +/* File: meshtype.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Okt. 95 */ +/**************************************************************************/ + +namespace netgen +{ + + /* + Classes for NETGEN + */ + + + + enum ELEMENT_TYPE { + SEGMENT = 1, SEGMENT3 = 2, + TRIG = 10, QUAD=11, TRIG6 = 12, QUAD6 = 13, QUAD8 = 14, + TET = 20, TET10 = 21, + PYRAMID = 22, PRISM = 23, PRISM12 = 24, + HEX = 25 + }; + + typedef int ELEMENT_EDGE[2]; // initial point, end point + typedef int ELEMENT_FACE[4]; // points, last one is -1 for trig + + +#define ELEMENT_MAXPOINTS 12 +#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 int GetTimeStamp(); + extern DLL_HEADER int NextTimeStamp(); + + class PointGeomInfo + { + public: + int trignum; // for STL Meshing + double u, v; // for OCC Meshing + + PointGeomInfo () + : trignum(-1), u(0), v(0) { ; } + }; + + 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 () { ; } + PointIndex (int ai) : i(ai) { ; } + PointIndex & operator= (const PointIndex &ai) { i = ai.i; return *this; } + PointIndex & operator= (int ai) { i = ai; return *this; } + operator int () const { return i; } + int GetInt () const { return i; } + PointIndex operator++ (int) { int hi = i; i++; return PointIndex(hi); } + PointIndex operator-- (int) { int hi = i; i--; return PointIndex(hi); } + +#ifdef BASE0 + enum { BASE = 0 }; +#else + enum { BASE = 1 }; +#endif + }; + + inline istream & operator>> (istream & ist, PointIndex & pi) + { + int i; ist >> i; pi = i; return ist; + } + + inline ostream & operator<< (ostream & ost, const PointIndex & pi) + { + return (ost << pi.GetInt()); + } + + + + + 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) { i++; return *this; } + ElementIndex & operator-- (int) { 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 () { ; } + SurfaceElementIndex (int ai) : i(ai) { ; } + SurfaceElementIndex & operator= (const SurfaceElementIndex & ai) + { i = ai.i; return *this; } + SurfaceElementIndex & operator= (int ai) { i = ai; return *this; } + operator int () const { return i; } + SurfaceElementIndex & operator++ (int) { i++; return *this; } + SurfaceElementIndex & operator-- (int) { i--; return *this; } + }; + + 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; + +#ifdef PARALLEL + bool isghost; +#endif + + public: + MeshPoint () + { +#ifdef PARALLEL + isghost = 0; +#endif + ; + } + + MeshPoint (const Point<3> & ap, int alayer = 1, POINTTYPE apt = INNERPOINT) + : Point<3> (ap), layer(alayer), singular(0.),type(apt) + { +#ifdef PARALLEL + isghost = 0; +#endif + ; + } + + void SetPoint (const Point<3> & ap) + { + Point<3>::operator= (ap); + layer = 0; + singular = 0; +#ifdef PARALLEL + isghost = 0; +#endif + } + + 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 + bool IsGhost () const { return isghost; } + void SetGhost ( bool aisghost ) { isghost = aisghost; } + + static MPI_Datatype MyGetMPIType ( ); +#endif + + }; + + inline ostream & operator<<(ostream & s, const MeshPoint & pt) + { + return (s << Point<3> (pt)); + } + + + + + typedef Array<MeshPoint, PointIndex::BASE> 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 + int index:16; + /// + ELEMENT_TYPE typ:6; + /// 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 + + /// order for hp-FEM + unsigned int orderx:6; + unsigned int ordery:6; + +#ifdef PARALLEL + bool isghost; + int partitionNumber; +#endif + + /// a linked list for all segments in the same face + SurfaceElementIndex next; + + public: + /// + Element2d (); + /// + Element2d (int anp); + /// + DLL_HEADER Element2d (ELEMENT_TYPE type); + /// + Element2d (int pi1, int pi2, int pi3); + /// + 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 ", typ); + } + } + /// + int GetNP() const { return np; } + /// + int GetNV() const + { + 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]; } + + /// + 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 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<Point2d> & 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; + /// matrix 2 * np + void GetDShape (const Point2d & p, class DenseMatrix & dshape) const; + void GetDShapeNew (const Point<2> & p, class MatrixFixWidth<2> & dshape) const; + /// matrix 2 * np + void GetPointMatrix (const Array<Point2d> & points, + class DenseMatrix & pmat) const; + + void ComputeIntegrationPointData () const; + + + double CalcJacobianBadness (const Array<Point2d> & points) const; + double CalcJacobianBadness (const T_POINTS & points, + const Vec<3> & n) const; + double CalcJacobianBadnessDirDeriv (const Array<Point2d> & points, + int pi, Vec2d & dir, double & dd) const; + + + + void Delete () { deleted = 1; pnum[0] = pnum[1] = pnum[2] = pnum[3] = PointIndex::BASE-1; } + 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; } + + + SurfaceElementIndex NextElement() { return next; } + + bool operator==(const Element2d & el2) const; + + int HasFace(const Element2d& el) const; + /// + int meshdocval; + /// + int hp_elnr; + +#ifdef PARALLEL + bool IsGhost () const { return isghost; } + void SetGhost ( bool aisghost ) { isghost = aisghost; } + + // by JS, only for 2D meshes ???? + int GetPartition () const { return partitionNumber; } + void SetPartition (int nr) { partitionNumber = nr; }; + +#else + bool IsGhost () const { return false; } +#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:6; + /// number of points (4..tet, 5..pyramid, 6..prism, 8..hex, 10..quad tet, 12..quad prism) + int np:5; + /// + 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 swaped + 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; + +#ifdef PARALLEL + /// number of partition for parallel computation + int partitionNumber; + bool isghost; +#endif + + public: + flagstruct flags; + + /// + Element (); + /// + 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; } + /// + int GetNV() const + { + switch (typ) + { + case TET: + case TET10: + return 4; + case PRISM12: + case PRISM: + return 6; + case PYRAMID: + return 5; + case HEX: + return 8; + default: +#ifdef DEBUG + PrintSysError ("Element3d::GetNV not implemented for typ ", typ) +#endif + ; + } + return np; + } + + 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]; } + + /// + 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 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 elemenet + double Volume (const T_POINTS & points) const; + /// + virtual void Print (ostream & ost) const; + /// + int GetNFaces () const + { + switch (typ) + { + case TET: + case TET10: return 4; + case PYRAMID: return 5; + case PRISM: + case PRISM12: return 5; + 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<Element> & locels) const; + /// split into 4 node tets, local point nrs + void GetTetsLocal (Array<Element> & locels) const; + /// returns coordinates of nodes + // void GetNodesLocal (Array<Point<3> > & points) const; + void GetNodesLocalNew (Array<Point<3> > & points) const; + + /// split surface into 3 node trigs + void GetSurfaceTriangles (Array<Element2d> & 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; + /// matrix 2 * np + void GetDShape (const Point<3> & p, class DenseMatrix & dshape) const; + void GetDShapeNew (const Point<3> & p, class MatrixFixWidth<3> & 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; + } + + + +#ifdef PARALLEL + int GetPartition () const { return partitionNumber; } + void SetPartition (int nr) { partitionNumber = nr; }; + + bool IsGhost () const { return isghost; } + void SetGhost ( const bool aisghost ) { isghost = aisghost; } +#else + bool IsGhost () const { return false; } + 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; + /// 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; + + private: + string* bcname; + + 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; } + + string GetBCName () const + { + if (! bcname ) + { + return "default"; + } + 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]; } + }; + + ostream & operator<<(ostream & s, const Segment & seg); + + + + + // 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; + + /// + string * 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; } + string GetBCName () const; + // 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; + }; + + 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 + */ + const char * optimize3d; + /// number of 3d optimization steps + int optsteps3d; + /** + 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 + **/ + const char * optimize2d; + /// number of 2d optimization steps + int optsteps2d; + /// power of error (to approximate max err optimization) + double opterrpow; + /// do block filling ? + int blockfill; + /// block filling up to distance + double filldist; + /// radius of local environment (times h) + double safety; + /// radius of active environment (times h) + double relinnersafety; + /// use local h ? + int uselocalh; + /// grading for local h + double grading; + /// use delaunay meshing + int delaunay; + /// maximal mesh size + double maxh; + /// minimal mesh size + double minh; + /// file for meshsize + const char * meshsizefilename; + /// start surfacemeshing from everywhere in surface + int startinsurface; + /// check overlapping surfaces (debug) + int checkoverlap; + /// check overlapping surface mesh before volume meshing + int checkoverlappingboundary; + /// check chart boundary (sometimes too restrictive) + int checkchartboundary; + /// safty factor for curvatures (elemetns per radius) + double curvaturesafety; + /// minimal number of segments per edge + double segmentsperedge; + /// use parallel threads + int parthread; + /// weight of element size w.r.t element shape + double elsizeweight; + /// init with default values + + + /// from mp3: + /// give up quality class, 2d meshing + int giveuptol2d; + /// give up quality class, 3d meshing + int giveuptol; + /// maximal outer steps + int maxoutersteps; + /// class starting star-shape filling + int starshapeclass; + /// if non-zero, baseelement must have baseelnp points + int baseelnp; + /// quality tolerances are handled less careful + int sloppy; + + /// limit for max element angle (150-180) + double badellimit; + + bool check_impossible; + + /// + int secondorder; + /// high order element curvature + int elementorder; + /// quad-dominated surface meshing + int quad; + /// + int inverttets; + /// + int inverttrigs; + /// + int autozrefine; + /// + MeshingParameters (); + /// + void Print (ostream & ost) const; + + void CopyFrom(const MeshingParameters & other); + }; + + + + 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 { UNDEFINED = 1, PERIODIC = 2, CLOSESURFACES = 3, CLOSEEDGES = 4}; + + + private: + class Mesh & mesh; + + /// identify points (thin layers, periodic b.c.) + INDEX_2_HASHTABLE<int> * identifiedpoints; + + /// the same, with info about the id-nr + INDEX_3_HASHTABLE<int> * identifiedpoints_nr; + + /// sorted by identification nr + TABLE<INDEX_2> idpoints_table; + + Array<ID_TYPE> 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; + + /// + INDEX_2_HASHTABLE<int> & 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<int,PointIndex::BASE> & 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<INDEX_2> & identpairs) const; + /// + int GetMaxNr () const { return maxidentnr; } + + /// remove secondorder + void SetMaxPointNr (int maxpnum); + + void Print (ostream & ost) const; + }; + + +} + + + + +#endif + diff --git a/contrib/Netgen/libsrc/meshing/msghandler.cpp b/contrib/Netgen/libsrc/meshing/msghandler.cpp new file mode 100644 index 0000000000..e2818858a4 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/msghandler.cpp @@ -0,0 +1,227 @@ +//File for handling warnings, errors, messages +#include <meshing.hpp> + +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) + { + 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<MyStr*> msgstatus_stack(0); +static Array<double> 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()); + 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 <<flush;} +double GetTime(){return 0;} +void MyError(const char * ch) +{ + cerr << ch << endl; +} +#endif +*/ + + +} diff --git a/contrib/Netgen/libsrc/meshing/msghandler.hpp b/contrib/Netgen/libsrc/meshing/msghandler.hpp new file mode 100644 index 0000000000..bab5717441 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/msghandler.hpp @@ -0,0 +1,57 @@ +#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 + diff --git a/contrib/Netgen/libsrc/meshing/netrule2.cpp b/contrib/Netgen/libsrc/meshing/netrule2.cpp new file mode 100644 index 0000000000..015ed6fa7c --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/netrule2.cpp @@ -0,0 +1,222 @@ +#include <mystdlib.h> +#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<Point2d> & 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 +{ + int left, right, allleft, allright; + + 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); + + allleft = 1; + allright = 1; + + for (int i = 1; i <= transfreezone.Size(); i++) + { + left = transfreezone.Get(i).X() * nx + transfreezone.Get(i).Y() + c < 1e-7; + right = transfreezone.Get(i).X() * nx + transfreezone.Get(i).Y() + c > -1e-7; + + if (!left) allleft = 0; + if (!right) allright = 0; + } + if (allleft || allright) return 0; + } + + return 1; +} + +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(); + } +*/ + + + + + + + + + + + +} diff --git a/contrib/Netgen/libsrc/meshing/netrule3.cpp b/contrib/Netgen/libsrc/meshing/netrule3.cpp new file mode 100644 index 0000000000..de0e35e424 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/netrule3.cpp @@ -0,0 +1,1138 @@ +#include <mystdlib.h> +#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<threeint> & 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<int> & freeset = *freesets.Get(fs); + const Array<twoint> & freesetedges = *freeedges.Get(fs); + // const Array<threeint> & 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<threeint> & 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<int> & pi, int newone) +{ + int fs; + int infreeset, cannot = 0; + + + ArrayMem<int,3> 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<int> & 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<int> & 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<int> activefaces; + int isin; + + + // MARK(triinfz); + + Array<threeint> & 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<int> 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<int> 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<int> & pi, int newone) +{ + int fs; + int infreeset, cannot = 0; + + + ArrayMem<int,4> 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<int> & 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<int> & 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<int,3> 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<int> cntpused(points.Size()); + Array<int> edge1, edge2; + Array<int> 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; +} + +} diff --git a/contrib/Netgen/libsrc/meshing/parallelmesh.cpp b/contrib/Netgen/libsrc/meshing/parallelmesh.cpp new file mode 100644 index 0000000000..03f436aef9 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/parallelmesh.cpp @@ -0,0 +1,1173 @@ +#ifdef PARALLEL + +#include <meshing.hpp> +#include "paralleltop.hpp" + +#define METIS4 + + +#ifdef METIS +namespace metis { + extern "C" { + +#ifdef METIS4 +#include <metis.h> + typedef idxtype idx_t; +#else +#include <metis.h> + typedef idx_t idxtype; +#endif + } +} + +using namespace metis; +#endif + + + +namespace netgen +{ + + template <> + inline MPI_Datatype MyGetMPIType<netgen::PointIndex> ( ) + { return MPI_INT; } + + + + + + void Mesh :: SendRecvMesh () + { + if (id == 0) + PrintMessage (1, "Send/Receive mesh"); + + { + // distribute global information + int nelglob, nseglob, nvglob; + if (id == 0) + { + paralleltop -> SetNV (GetNV()); + paralleltop -> SetNE (GetNE()); + paralleltop -> SetNSegm (GetNSeg()); + paralleltop -> SetNSE (GetNSE()); + + nelglob = GetNE(); + nseglob = GetNSE(); + nvglob = GetNV(); + } + + MyMPI_Bcast (dimension); + MyMPI_Bcast (nelglob); + MyMPI_Bcast (nseglob); + MyMPI_Bcast (nvglob); + + if (id > 0) + { + paralleltop -> SetNEGlob (nelglob); + paralleltop -> SetNSEGlob (nseglob); + paralleltop -> SetNVGlob (nvglob); + } + } + + + + { + // distribute number of local elements + if (id == 0) + { + Array<int> num_els_on_proc(ntasks); + num_els_on_proc = 0; + for (ElementIndex ei = 0; ei < GetNE(); ei++) + num_els_on_proc[(*this)[ei].GetPartition()]++; + + MPI_Scatter (&num_els_on_proc[0], 1, MPI_INT, + MPI_IN_PLACE, -1, MPI_INT, 0, MPI_COMM_WORLD); + } + else + { + int nelloc; + MPI_Scatter (NULL, 0, MPI_INT, + &nelloc, 1, MPI_INT, 0, MPI_COMM_WORLD); + + paralleltop -> SetNE (nelloc); + } + } + + if (id == 0) + SendMesh (); + else + ReceiveParallelMesh(); + } + + + + + + + + void Mesh :: SendMesh () const + { + Array<MPI_Request> sendrequests; + + PrintMessage ( 3, "Sending vertices"); + + + Array<int> num_els_on_proc(ntasks); + num_els_on_proc = 0; + for (ElementIndex ei = 0; ei < GetNE(); ei++) + num_els_on_proc[(*this)[ei].GetPartition()]++; + + TABLE<ElementIndex> els_of_proc (num_els_on_proc); + for (ElementIndex ei = 0; ei < GetNE(); ei++) + els_of_proc.Add ( (*this)[ei].GetPartition(), ei); + + + Array<int> num_sels_on_proc(ntasks); + num_sels_on_proc = 0; + for (SurfaceElementIndex ei = 0; ei < GetNSE(); ei++) + num_sels_on_proc[(*this)[ei].GetPartition()]++; + + TABLE<SurfaceElementIndex> sels_of_proc (num_sels_on_proc); + for (SurfaceElementIndex ei = 0; ei < GetNSE(); ei++) + sels_of_proc.Add ( (*this)[ei].GetPartition(), ei); + + + + + Array<int, PointIndex::BASE> vert_flag (GetNV()); + Array<int, PointIndex::BASE> num_procs_on_vert (GetNV()); + Array<int> num_verts_on_proc (ntasks); + + num_verts_on_proc = 0; + num_procs_on_vert = 0; + vert_flag = -1; + + Array<int> nelloc (ntasks); + nelloc = 0; + Array<int> nselloc (ntasks); + nselloc = 0; + + + for (int dest = 1; dest < ntasks; dest++) + { + FlatArray<ElementIndex> 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++) + { + PointIndex epi = el[i]; + if (vert_flag[epi] < dest) + { + vert_flag[epi] = dest; + + num_verts_on_proc[dest]++; + num_procs_on_vert[epi]++; + + paralleltop -> SetDistantPNum ( dest, epi, num_verts_on_proc[dest]); + } + } + nelloc[dest] ++; + paralleltop -> SetDistantEl ( dest, els[hi]+1, nelloc[dest] ); + } + + + FlatArray<SurfaceElementIndex> 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++) + { + PointIndex epi = el[i]; + if (vert_flag[epi] < dest) + { + vert_flag[epi] = dest; + + num_verts_on_proc[dest]++; + num_procs_on_vert[epi]++; + + paralleltop -> SetDistantPNum ( dest, epi, num_verts_on_proc[dest]); + } + } + nselloc[dest] ++; + paralleltop -> SetDistantSurfEl ( dest, sels[hi]+1, nselloc[dest] ); + } + } + + TABLE<PointIndex> verts_of_proc (num_verts_on_proc); + TABLE<int, PointIndex::BASE> procs_of_vert (num_procs_on_vert); + TABLE<int, PointIndex::BASE> loc_num_of_vert (num_procs_on_vert); + + vert_flag = -1; + for (int dest = 1; dest < ntasks; dest++) + { + FlatArray<ElementIndex> 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++) + { + PointIndex epi = el[i]; + if (vert_flag[epi] < dest) + { + vert_flag[epi] = dest; + procs_of_vert.Add (epi, dest); + } + } + } + + FlatArray<SurfaceElementIndex> 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++) + { + PointIndex epi = el[i]; + if (vert_flag[epi] < dest) + { + vert_flag[epi] = dest; + procs_of_vert.Add (epi, dest); + } + } + } + + } + + for (int vert = 1; vert <= GetNP(); vert++ ) + { + FlatArray<int> 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()); + } + } + + for (int dest = 1; dest < ntasks; dest++) + { + FlatArray<PointIndex> verts = verts_of_proc[dest]; + + sendrequests.Append (MyMPI_ISend (verts, dest, MPI_TAG_MESH+1)); + + MPI_Datatype mptype = MeshPoint::MyGetMPIType(); + + int numv = verts.Size(); + + MPI_Datatype newtype; + Array<int> blocklen (numv); + blocklen = 1; + + MPI_Type_indexed (numv, &blocklen[0], + reinterpret_cast<int*> (&verts[0]), + mptype, &newtype); + MPI_Type_commit (&newtype); + + MPI_Request request; + MPI_Isend( &points[0], 1, newtype, dest, MPI_TAG_MESH+1, MPI_COMM_WORLD, &request); + sendrequests.Append (request); + } + + + Array<int> num_distpnums(ntasks); + num_distpnums = 0; + + for (int vert = 1; vert <= GetNP(); vert++) + { + FlatArray<int> procs = procs_of_vert[vert]; + for (int j = 0; j < procs.Size(); j++) + num_distpnums[procs[j]] += 3 * (procs.Size()-1); + } + + TABLE<int> distpnums (num_distpnums); + + for (int vert = 1; vert <= GetNP(); vert++) + { + FlatArray<int> 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)); + + + + PrintMessage ( 3, "Sending elements" ); + + Array<int> elarraysize (ntasks); + elarraysize = 0; + for ( int ei = 1; ei <= GetNE(); ei++) + { + const Element & el = VolumeElement (ei); + int dest = el.GetPartition(); + elarraysize[dest] += 3 + el.GetNP(); + } + + TABLE<int> elementarrays(elarraysize); + + for (int ei = 1; ei <= GetNE(); ei++) + { + const Element & el = VolumeElement (ei); + int dest = el.GetPartition(); + + 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)); + + + PrintMessage ( 3, "Sending Face Descriptors" ); + + Array<double> 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)); + + PrintMessage ( 3, "Sending Surface elements" ); + + Array <int> nlocsel(ntasks), bufsize(ntasks); + nlocsel = 0; + bufsize = 1; + + for (int sei = 1; sei <= GetNSE(); sei++ ) + { + const Element2d & sel = SurfaceElement (sei); + int dest = sel.GetPartition(); + nlocsel[dest] ++; + bufsize[dest] += 4 + 2*sel.GetNP(); + } + + TABLE<int> selbuf(bufsize); + + for (int dest = 1; dest < ntasks; dest++ ) + selbuf.Add (dest, nlocsel[dest]); + + for (int sei = 1; sei <= GetNSE(); sei ++ ) + { + const Element2d & sel = SurfaceElement (sei); + int dest = sel.GetPartition(); + + 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); + } + } + + for (int dest = 1; dest < ntasks; dest++) + sendrequests.Append (MyMPI_ISend(selbuf[dest], dest, MPI_TAG_MESH+4)); + + PrintMessage ( 3, "Sending Edge Segments"); + + Array <int> nlocseg(ntasks), segi(ntasks); + for ( int i = 0; i < ntasks; i++) + { + nlocseg[i] = 0; + bufsize[i] = 0; + segi[i] = 0; + } + + for (int segi = 1; segi <= GetNSeg(); segi ++ ) + { + Array<int> volels; + const MeshTopology & topol = GetTopology(); + topol . GetSegmentSurfaceElements ( segi, volels ); + for (int j = 0; j < volels.Size(); j++) + { + int ei = volels[j]; + if ( ei > 0 && ei <= GetNSE() ) + { + const Element2d & el = SurfaceElement (ei); + int dest = el.GetPartition(); + nlocseg[dest] ++; + bufsize[dest] += 14; + } + } + } + + TABLE<double> segmbuf(bufsize); + + for ( int ls=1; ls <= GetNSeg(); ls++) + { + Array<int> volels; + GetTopology().GetSegmentSurfaceElements ( ls, volels ); + const Segment & seg = LineSegment (ls); + + for (int j = 0; j < volels.Size(); j++) + { + int ei = volels[j]; + if ( ei > 0 && ei <= GetNSE() ) + { + const Element2d & el = SurfaceElement (ei); + int dest = el.GetPartition(); + + if ( dest > 0 ) + { + segmbuf.Add (dest, ls); + segmbuf.Add (dest, seg.si); + segmbuf.Add (dest, seg.pnums[0]); + segmbuf.Add (dest, seg.pnums[1]); + segmbuf.Add (dest, seg.geominfo[0].trignum); + segmbuf.Add (dest, seg.geominfo[1].trignum); + segmbuf.Add (dest, seg.surfnr1); + segmbuf.Add (dest, seg.surfnr2); + segmbuf.Add (dest, seg.edgenr); + segmbuf.Add (dest, seg.epgeominfo[0].dist); + segmbuf.Add (dest, seg.epgeominfo[1].edgenr); + segmbuf.Add (dest, seg.epgeominfo[1].dist); + segmbuf.Add (dest, seg.singedge_right); + segmbuf.Add (dest, seg.singedge_left); + segi[dest] += 14; + } + paralleltop -> SetDistantSegm ( dest, ls, int ( segi[dest] / 14 ) ); + } + } + } + + for ( int dest = 1; dest < ntasks; dest++) + sendrequests.Append (MyMPI_ISend(segmbuf[dest], dest, MPI_TAG_MESH+5)); + + MPI_Waitall (sendrequests.Size(), &sendrequests[0], MPI_STATUS_IGNORE); + + MPI_Barrier(MPI_COMM_WORLD); + } + + + + + + + + + // 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); + + + // string st; + + // receive vertices + NgProfiler::StartTimer (timer_pts); + + Array<int> verts; + MyMPI_Recv (verts, 0, MPI_TAG_MESH+1); + + int numvert = verts.Size(); + paralleltop -> SetNV (numvert); + + // INDEX_CLOSED_HASHTABLE<int> glob2loc_vert_ht (3*numvert+1); + INDEX_HASHTABLE<int> 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, MPI_COMM_WORLD, &status); + + Array<int> dist_pnums; + MyMPI_Recv (dist_pnums, 0, MPI_TAG_MESH+1); + + 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; + + { + Element el; + + Array<int> elarray; + MyMPI_Recv (elarray, 0, MPI_TAG_MESH+2); + + NgProfiler::RegionTimer reg(timer_els); + + for (int ind = 0, elnum = 1; ind < elarray.Size(); elnum++) + { + paralleltop->SetLoc2Glob_VolEl ( elnum, elarray[ind++]); + + el.SetIndex(elarray[ind++]); + el.SetNP(elarray[ind++]); + + for ( int j = 0; j < el.GetNP(); j++) + el[j] = glob2loc_vert_ht.Get (elarray[ind++]); + + AddVolumeElement (el); + } + } + + { + Array<double> fddata; + MyMPI_Recv (fddata, 0, MPI_TAG_MESH+3); + 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<int> selbuf; + + MyMPI_Recv ( selbuf, 0, MPI_TAG_MESH+4); + + 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++]; + } + + tri.SetGhost(isghost); + + paralleltop->SetLoc2Glob_SurfEl ( sel+1, globsel ); + AddSurfaceElement (tri); + sel ++; + } + } + + + + { + Array<double> segmbuf; + MyMPI_Recv ( segmbuf, 0, MPI_TAG_MESH+5); + + 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++; + } + + } + } + + MPI_Barrier(MPI_COMM_WORLD); + + int timerloc = NgProfiler::CreateTimer ("Update local mesh"); + int timerloc2 = NgProfiler::CreateTimer ("CalcSurfacesOfNode"); + + NgProfiler::RegionTimer regloc(timerloc); + 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(); + + SetNextMajorTimeStamp(); + // paralleltop->Print(); + } + + + + + + // distribute the mesh to the slave processors + // call it only for the master ! + void Mesh :: Distribute () + { + 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; + + // send partition + MyMPI_SendCmd ("mesh"); + SendRecvMesh (); + + paralleltop -> UpdateCoarseGrid(); + // paralleltop -> Print(); + } + + + + + +#ifdef METIS + 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<idxtype> 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<idxtype> 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 ... " << flush; + METIS_PartMeshDual (&ne, &nn, &elmnts[0], &etype, &numflag, &nparts, + &edgecut, &epart[0], &npart[0]); +#else + cout << "call metis-5 ... " << endl; + idx_t options[METIS_NOPTIONS]; + + Array<idx_t> 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<int> 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<int> 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<int> nodesinpart(ntasks); + + for ( int el = 1; el <= ne; el++ ) + { + Element & volel = VolumeElement(el); + nodesinpart = 0; + + // VolumeElement(el).SetPartition(part[ volel[1] ] + 1); + + 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); + + } + + /* + for ( int i=1; i<=ne; i++) + { + neloc[ VolumeElement(i).GetPartition() ] ++; + } + */ + + delete [] xadj; + delete [] part; + delete [] adjacency; +#else + cout << "parthybridmesh not available" << endl; +#endif + } + + + void Mesh :: PartDualHybridMesh ( ) // Array<int> & 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<int, 0> facevolels1(nfaces), facevolels2(nfaces); + facevolels1 = -1; + facevolels2 = -1; + + Array<int, 0> elfaces; + xadj = new idxtype[ne+1]; + part = new idxtype[ne]; + + Array<int, 0> 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<int> 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<int> nodesinpart(ntasks); + + for ( int el = 1; el <= ne; el++ ) + { + // Element & volel = VolumeElement(el); + nodesinpart = 0; + + VolumeElement(el).SetPartition(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 + int ne = GetNSE(); + int nv = GetNV(); + + Array<idxtype> xadj(ne+1); + Array<idxtype> adjacency(ne*4); + + // first, build the vertex 2 element table: + Array<int, PointIndex::BASE> 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<SurfaceElementIndex, PointIndex::BASE> 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<int> 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; + + int weightflag = 0; + int numflag = 0; + int nparts = ntasks - 1; + + int options[5]; + options[0] = 0; + int edgecut; + Array<idxtype> part(ne); + + for ( int el = 0; el < ne; el++ ) + BubbleSort (adjacency.Range (xadj[el], xadj[el+1])); + +#ifdef METIS4 + 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 + + + for (SurfaceElementIndex sei = 0; sei < ne; sei++) + (*this) [sei].SetPartition (part[sei]+1); +#else + cout << "partdualmesh not available" << endl; +#endif + + } + + + + + + + + void Mesh :: UpdateOverlap() + { + cout << "UpdateOverlap depreciated" << endl; + } + + + + + + + + +} + + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/paralleltop.cpp b/contrib/Netgen/libsrc/meshing/paralleltop.cpp new file mode 100644 index 0000000000..7467b03b36 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/paralleltop.cpp @@ -0,0 +1,896 @@ +#ifdef PARALLEL + + +#include <meshing.hpp> +#include "paralleltop.hpp" + + +namespace netgen +{ + + static MPI_Group MPI_HIGHORDER_WORLD; + static MPI_Comm MPI_HIGHORDER_COMM; + + void MyMPI_ExchangeTable (TABLE<int> & send_verts, + TABLE<int> & recv_verts, int tag, + MPI_Comm comm = MPI_COMM_WORLD) + { + int ntasks, rank; + MPI_Comm_size(comm, &ntasks); + MPI_Comm_rank(comm, &rank); + + Array<MPI_Request> requests; + for (int dest = 0; dest < ntasks; dest++) + if (dest != rank) + requests.Append (MyMPI_ISend (send_verts[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_verts.SetEntrySize (src, size, sizeof(int)); + requests.Append (MyMPI_IRecv (recv_verts[src], src, tag, comm)); + } + MPI_Waitall (requests.Size(), &requests[0], MPI_STATUS_IGNORE); + } + + + + + void ParallelMeshTopology :: Reset () + { + *testout << "ParallelMeshTopology::Reset" << endl; + + if ( ntasks == 1 ) return; + + int nvold = nv; + + ne = mesh.GetNE(); + nv = mesh.GetNV(); + nseg = mesh.GetNSeg(); + nsurfel = mesh.GetNSE(); + + ned = mesh.GetTopology().GetNEdges(); + nfa = mesh.GetTopology().GetNFaces(); + + loc2distedge.ChangeSize (ned); + for (int i = 0; i < ned; i++) + if (loc2distedge[i].Size() == 0) + loc2distedge.Add (i, -1); // will be the global nr + + loc2distface.ChangeSize (nfa); + for (int i = 0; i < nfa; i++) + if (loc2distface[i].Size() == 0) + loc2distface.Add (i, -1); // will be the global nr + + if ( nvold == nv ) return; + + SetNV(nv); + SetNE(ne); + } + + + ParallelMeshTopology :: ~ParallelMeshTopology () + { + ; + } + + + + ParallelMeshTopology :: ParallelMeshTopology ( const netgen::Mesh & amesh ) + : mesh(amesh) + { + ned = 0; + nfa = 0; + nv = 0; + ne = 0; + np = 0; + nseg = 0; + nsurfel = 0; + neglob = 0; + nvglob = 0; + + nparel = 0; + + coarseupdate = 0; + } + + + + void ParallelMeshTopology :: Print() const + { + + (*testout) << endl << "TOPOLOGY FOR PARALLEL MESHES" << endl << endl; + + for ( int i = 1; i <= nv; i++ ) + if ( IsExchangeVert (i) ) + { + (*testout) << "exchange point " << i << ": global " << GetLoc2Glob_Vert(i) << endl; + for ( int dest = 0; dest < ntasks; dest ++) + if ( dest != id ) + if ( GetDistantPNum( dest, i ) > 0 ) + (*testout) << " p" << dest << ": " << GetDistantPNum ( dest, i ) << endl; + } + + for ( int i = 1; i <= ned; i++ ) + if ( IsExchangeEdge ( i ) ) + { + int v1, v2; + mesh . GetTopology().GetEdgeVertices(i, v1, v2); + (*testout) << "exchange edge " << i << ": global vertices " << GetLoc2Glob_Vert(v1) << " " + << GetLoc2Glob_Vert(v2) << endl; + for ( int dest = 0; dest < ntasks; dest++) + if ( GetDistantEdgeNum ( dest, i ) > 0 ) + if ( dest != id ) + (*testout) << " p" << dest << ": " << GetDistantEdgeNum ( dest, i ) << endl; + } + + for ( int i = 1; i <= nfa; i++ ) + if ( IsExchangeFace(i) ) + { + Array<int> facevert; + mesh . GetTopology().GetFaceVertices(i, facevert); + + (*testout) << "exchange face " << i << ": global vertices " ; + for ( int fi=0; fi < facevert.Size(); fi++) + (*testout) << GetLoc2Glob_Vert(facevert[fi]) << " "; + (*testout) << endl; + for ( int dest = 0; dest < ntasks; dest++) + if ( dest != id ) + { + if ( GetDistantFaceNum ( dest, i ) >= 0 ) + (*testout) << " p" << dest << ": " << GetDistantFaceNum ( dest, i ) << endl; + } + } + + + /* + for ( int i = 1; i < mesh.GetNE(); i++) + { + if ( !IsExchangeElement(i) ) continue; + Array<int> vert; + const Element & el = mesh.VolumeElement(i); + + (*testout) << "parallel local element " << i << endl; + + (*testout) << "vertices " ; + for ( int j = 0; j < el.GetNV(); j++) + (*testout) << el.PNum(j+1) << " "; + (*testout) << "is ghost " << IsGhostEl(i) << endl; + (*testout) << endl; + } + */ + } + + + + + + int ParallelMeshTopology :: GetDistantPNum ( int proc, int locpnum ) const + { + if ( proc == 0 ) + return loc2distvert[locpnum][0]; + + for (int i = 1; i < loc2distvert[locpnum].Size(); i += 2) + if ( loc2distvert[locpnum][i] == proc ) + return loc2distvert[locpnum][i+1]; + + return -1; + } + + int ParallelMeshTopology :: GetDistantFaceNum ( int proc, int locfacenum ) const + { + if ( proc == 0 ) + return loc2distface[locfacenum-1][0]; + + for ( int i = 1; i < loc2distface[locfacenum-1].Size(); i+=2 ) + if ( loc2distface[locfacenum-1][i] == proc ) + return loc2distface[locfacenum-1][i+1]; + + return -1; + } + + int ParallelMeshTopology :: GetDistantEdgeNum ( int proc, int locedgenum ) const + { + if ( proc == 0 ) + return loc2distedge[locedgenum-1][0]; + + for ( int i = 1; i < loc2distedge[locedgenum-1].Size(); i+=2 ) + if ( loc2distedge[locedgenum-1][i] == proc ) + return loc2distedge[locedgenum-1][i+1]; + + return -1; + } + + int ParallelMeshTopology :: GetDistantElNum ( int proc, int locelnum ) const + { + if ( proc == 0 ) + return loc2distel[locelnum-1][0]; + + for ( int i = 1; i < loc2distel[locelnum-1].Size(); i+=2 ) + if ( loc2distel[locelnum-1][i] == proc ) + return loc2distel[locelnum-1][i+1]; + + return -1; + } + + + + // gibt anzahl an distant pnums zurueck + // * pnums entspricht Array<int[2] > + int ParallelMeshTopology :: GetDistantPNums ( int locpnum, int * distpnums ) const + { + distpnums[0] = 0; + distpnums[1] = loc2distvert[locpnum][0]; + for ( int i = 1; i < loc2distvert[locpnum].Size(); i++ ) + distpnums[i+1] = loc2distvert[locpnum][i]; + + int size = loc2distvert[locpnum].Size() / 2 + 1; + return size; + } + + int ParallelMeshTopology :: GetDistantFaceNums ( int locfacenum, int * distfacenums ) const + { + distfacenums[0] = 0; + distfacenums[1] = loc2distface[locfacenum-1][0]; + + for ( int i = 1; i < loc2distface[locfacenum-1].Size(); i++ ) + distfacenums[i+1] = loc2distface[locfacenum-1][i]; + + int size = loc2distface[locfacenum-1].Size() / 2 + 1; + return size; + } + + int ParallelMeshTopology :: GetDistantEdgeNums ( int locedgenum, int * distedgenums ) const + { + distedgenums[0] = 0; + distedgenums[1] = loc2distedge[locedgenum-1][0]; + + for ( int i = 1; i < loc2distedge[locedgenum-1].Size(); i++ ) + distedgenums[i+1] = loc2distedge[locedgenum-1][i]; + + int size = loc2distedge[locedgenum-1].Size() / 2 + 1; + return size; + } + + int ParallelMeshTopology :: GetDistantElNums ( int locelnum, int * distelnums ) const + { + distelnums[0] = 0; + distelnums[1] = loc2distel[locelnum-1][0]; + + for ( int i = 1; i < loc2distel[locelnum-1].Size(); i++ ) + distelnums[i+1] = loc2distel[locelnum-1][i]; + + int size = loc2distel[locelnum-1].Size() / 2 + 1; + return size; + } + + + + + void ParallelMeshTopology :: SetDistantFaceNum ( int dest, int locnum, int distnum ) + { + if ( dest == 0 ) + { + loc2distface[locnum-1][0] = distnum; + return; + } + + for ( int i = 1; i < loc2distface[locnum-1].Size(); i+=2 ) + if ( loc2distface[locnum-1][i] == dest ) + { + loc2distface[locnum-1][i+1] = distnum; + return; + } + + loc2distface.Add(locnum-1, dest); + loc2distface.Add(locnum-1, distnum); + } + + void ParallelMeshTopology :: SetDistantPNum ( int dest, int locnum, int distnum ) + { + if ( dest == 0 ) + { + loc2distvert[locnum][0] = distnum; // HERE + return; + } + + for ( int i = 1; i < loc2distvert[locnum].Size(); i+=2 ) + if ( loc2distvert[locnum][i] == dest ) + { + loc2distvert[locnum][i+1] = distnum; + return; + } + + loc2distvert.Add (locnum, dest); + loc2distvert.Add (locnum, distnum); + } + + + void ParallelMeshTopology :: SetDistantEdgeNum ( int dest, int locnum, int distnum ) + { + if ( dest == 0 ) + { + loc2distedge[locnum-1][0] = distnum; + return; + } + + for ( int i = 1; i < loc2distedge[locnum-1].Size(); i+=2 ) + if ( loc2distedge[locnum-1][i] == dest ) + { + loc2distedge[locnum-1][i+1] = distnum; + return; + } + + loc2distedge.Add (locnum-1, dest); + loc2distedge.Add (locnum-1, distnum); + } + + void ParallelMeshTopology :: SetDistantEl ( int dest, int locnum, int distnum ) + { + if ( dest == 0 ) + { + loc2distel[locnum-1][0] = distnum; + return; + } + + for ( int i = 1; i < loc2distel[locnum-1].Size(); i+=2 ) + if ( loc2distel[locnum-1][i] == dest ) + { + loc2distel[locnum-1][i+1] = distnum; + return; + } + + + loc2distel.Add (locnum-1, dest); + loc2distel.Add (locnum-1, distnum); + } + + void ParallelMeshTopology :: SetDistantSurfEl ( int dest, int locnum, int distnum ) + { + if ( dest == 0 ) + { + loc2distsurfel[locnum-1][0] = distnum; + return; + } + + for ( int i = 1; i < loc2distsurfel[locnum-1].Size(); i+=2 ) + if ( loc2distsurfel[locnum-1][i] == dest ) + { + loc2distsurfel[locnum-1][i+1] = distnum; + return; + } + + loc2distsurfel.Add (locnum-1, dest); + loc2distsurfel.Add (locnum-1, distnum); + } + + void ParallelMeshTopology :: SetDistantSegm ( int dest, int locnum, int distnum ) + { + if ( dest == 0 ) + { + loc2distsegm[locnum-1][0] = distnum; + return; + } + + for (int i = 1; i < loc2distsegm[locnum-1].Size(); i+=2 ) + if ( loc2distsegm[locnum-1][i] == dest ) + { + loc2distsegm[locnum-1][i+1] = distnum; + return; + } + + loc2distsegm.Add (locnum-1, dest); + loc2distsegm.Add (locnum-1, distnum); + } + + void ParallelMeshTopology :: GetVertNeighbours ( int vnum, Array<int> & dests ) const + { + dests.SetSize(0); + int i = 1; + while ( i < loc2distvert[vnum].Size() ) + { + dests.Append ( loc2distvert[vnum][i] ); + i+=2; + } + } + + + void ParallelMeshTopology :: Update () + { + ne = mesh.GetNE(); + nv = mesh.GetNV(); + nseg = mesh.GetNSeg(); + nsurfel = mesh.GetNSE(); + + ned = mesh.GetTopology().GetNEdges(); + nfa = mesh.GetTopology().GetNFaces(); + } + + + + + + + + + void ParallelMeshTopology :: UpdateRefinement () + { + ; + } + + + + + void ParallelMeshTopology :: UpdateCoarseGridGlobal () + { + if (id == 0) + PrintMessage ( 3, "UPDATE GLOBAL COARSEGRID STARTS" ); // JS + + + MPI_Group MPI_GROUP_WORLD; + int process_ranks[] = { 0 }; + MPI_Comm_group (MPI_COMM_WORLD, &MPI_GROUP_WORLD); + MPI_Group_excl (MPI_GROUP_WORLD, 1, process_ranks, &MPI_HIGHORDER_WORLD); + MPI_Comm_create (MPI_COMM_WORLD, MPI_HIGHORDER_WORLD, &MPI_HIGHORDER_COMM); + + + int timer = NgProfiler::CreateTimer ("UpdateCoarseGridGlobal"); + NgProfiler::RegionTimer reg(timer); + + + *testout << "ParallelMeshTopology :: UpdateCoarseGridGlobal" << endl; + + const MeshTopology & topology = mesh.GetTopology(); + + Array<int> sendarray, recvarray; + + nfa = topology . GetNFaces(); + ned = topology . GetNEdges(); + np = mesh . GetNP(); + nv = mesh . GetNV(); + ne = mesh . GetNE(); + nseg = mesh.GetNSeg(); + nsurfel = mesh.GetNSE(); + + // low order processor - save mesh partition + if ( id == 0 ) + { + for ( int eli = 1; eli <= ne; eli++ ) + loc2distel[eli-1][0] = eli; + + for ( int i = 1; i <= mesh .GetNV(); i++) + loc2distvert[i][0] = i; + + for ( int i = 0; i < mesh . GetNSeg(); i++) + loc2distsegm[i][0] = i+1; + + for ( int i = 0; i < mesh . GetNSE(); i++) + loc2distsurfel[i][0] = i+1; + + for ( int i = 0; i < topology .GetNEdges(); i++) + loc2distedge[i][0] = i+1; + + for ( int i = 0; i < topology .GetNFaces(); i++) + loc2distface[i][0] = i+1; + } + + + + if ( id == 0 ) + { + sendarray.Append (nfa); + sendarray.Append (ned); + + Array<int> edges, pnums, faces, elpnums; + sendarray.Append (ne); + for ( int el = 1; el <= ne; el++ ) + { + topology.GetElementFaces (el, faces); + topology.GetElementEdges ( el, edges ); + const Element & volel = mesh.VolumeElement (el); + + int globeli = GetLoc2Glob_VolEl(el); + // cout << "el = " << el << ", globeli = " << globeli << endl; + + sendarray. Append ( globeli ); + sendarray. Append ( faces.Size() ); + sendarray. Append ( edges.Size() ); + sendarray. Append ( volel.GetNP() ); + + for ( int i = 0; i < faces.Size(); i++ ) + sendarray. Append(faces[i] ); + for ( int i = 0; i < edges.Size(); i++ ) + sendarray. Append(edges[i] ); + + for ( int i = 0; i < volel.GetNP(); i++ ) + if (id == 0) + sendarray. Append(volel[i] ); + else + sendarray. Append(GetLoc2Glob_Vert (volel[i])); + } + + + sendarray.Append (nsurfel); + for (int el = 1; el <= nsurfel; el++) + { + topology.GetSurfaceElementEdges ( el, edges ); + const Element2d & surfel = mesh.SurfaceElement (el); + + sendarray. Append ( el ); + sendarray. Append ( edges.Size() ); + sendarray. Append ( surfel.GetNP() ); + + for ( int i = 0; i < edges.Size(); i++ ) + sendarray. Append(edges[i] ); + + for ( int i = 0; i < surfel.GetNP(); i++ ) + sendarray. Append(surfel[i] ); + } + + } + + + if (id == 0) + MyMPI_Bcast ( sendarray ); + else + MyMPI_Bcast ( recvarray ); + + + if (id != 0) + { + Array<int,1> glob2loc_el; + + glob2loc_el.SetSize (neglob); + glob2loc_el = -1; + for ( int locel = 1; locel <= mesh.GetNE(); locel++) + glob2loc_el[GetLoc2Glob_VolEl(locel)] = locel; + + int ii = 0; + nfaglob = recvarray[ii++]; + nedglob = recvarray[ii++]; + + Array<int> faces, edges; + Array<int> pnums, globalpnums; + + int recv_ne = recvarray[ii++]; + for (int hi = 0; hi < recv_ne; hi++) + { + int globvolel = recvarray[ii++]; + int distnfa = recvarray[ii++]; + int distned = recvarray[ii++]; + int distnp = recvarray[ii++]; + + int volel = glob2loc_el[globvolel]; + if (volel != -1) + { + topology.GetElementFaces( volel, faces); + topology.GetElementEdges ( volel, edges); + const Element & volelement = mesh.VolumeElement (volel); + + for ( int i = 0; i < faces.Size(); i++) + SetDistantFaceNum ( 0, faces[i], recvarray[ii++]); + + for ( int i = 0; i < edges.Size(); i++) + SetDistantEdgeNum ( 0, edges[i], recvarray[ii++]); + + for ( int i = 0; i < volelement.GetNP(); i++) + SetDistantPNum ( 0, volelement[i], recvarray[ii++]); + } + else + ii += distnfa + distned + distnp; + } + + + Array<int,1> glob2loc_sel; + + int recv_nse = recvarray[ii++]; + nseglob = recv_nse; + + glob2loc_sel.SetSize (nseglob); + glob2loc_sel = -1; + for ( int locel = 1; locel <= mesh.GetNSE(); locel++) + glob2loc_sel[GetLoc2Glob_SurfEl(locel)] = locel; + + + for (int hi = 0; hi < recv_nse; hi++) + { + int globvolel = recvarray[ii++]; + int distned = recvarray[ii++]; + int distnp = recvarray[ii++]; + + int surfel = glob2loc_sel[globvolel]; + if (surfel != -1) + { + topology.GetSurfaceElementEdges ( surfel, edges); + const Element2d & element = mesh.SurfaceElement (surfel); + + for ( int i = 0; i < edges.Size(); i++) + SetDistantEdgeNum ( 0, edges[i], recvarray[ii++]); + + for ( int i = 0; i < element.GetNP(); i++) + SetDistantPNum ( 0, element[i], recvarray[ii++]); + } + else + ii += distned + distnp; + } + + + } + + if (id != 0) + { + *testout << "l2d - vert = " << loc2distvert << endl; + *testout << "l2d - edge = " << loc2distedge << endl; + *testout << "l2d - el = " << loc2distel << endl; + *testout << "l2d - sel = " << loc2distsurfel << endl; + } + + coarseupdate = 1; + } + + + + + + + void ParallelMeshTopology :: UpdateCoarseGrid () + { + static int timer = NgProfiler::CreateTimer ("UpdateCoarseGrid"); + NgProfiler::RegionTimer reg(timer); + + + (*testout) << "UPDATE COARSE GRID PARALLEL TOPOLOGY " << endl; + if (id == 0) + PrintMessage (1, "UPDATE COARSE GRID PARALLEL TOPOLOGY "); + + + // find exchange edges - first send exchangeedges locnum, v1, v2 + // receive distant distnum, v1, v2 + // find matching + const MeshTopology & topology = mesh.GetTopology(); + + UpdateCoarseGridGlobal(); + + MPI_Barrier (MPI_COMM_WORLD); + + if ( id == 0 ) + { + return; + } + + + Array<int> sendarray, recvarray; + + nfa = topology . GetNFaces(); + ned = topology . GetNEdges(); + np = mesh . GetNP(); + nv = mesh . GetNV(); + ne = mesh . GetNE(); + nseg = mesh.GetNSeg(); + nsurfel = mesh.GetNSE(); + + + static int timerv = NgProfiler::CreateTimer ("UpdateCoarseGrid - ex vertices"); + static int timere = NgProfiler::CreateTimer ("UpdateCoarseGrid - ex edges"); + static int timerf = NgProfiler::CreateTimer ("UpdateCoarseGrid - ex faces"); + + + Array<int,1> glob2loc; + Array<int> cnt_send(ntasks-1); + + NgProfiler::StartTimer (timere); + + // exchange edges + int maxedge = 0; + for (int edge = 1; edge <= ned; edge++) + maxedge = max (maxedge, GetDistantEdgeNum (0, edge)); + + glob2loc.SetSize (maxedge); + glob2loc = -1; + + for (int edge = 1; edge <= ned; edge++) + glob2loc[GetDistantEdgeNum(0, edge)] = edge; + + 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]+=2; + } + } + + TABLE<int> 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)) + { + send_edges.Add (dest-1, GetDistantEdgeNum(0, edge)); + send_edges.Add (dest-1, edge); + } + } + } + + + // *testout << "send exchange edges: " << send_edges << endl; + + TABLE<int> recv_edges(ntasks-1); + MyMPI_ExchangeTable (send_edges, recv_edges, MPI_TAG_MESH+9, MPI_HIGHORDER_COMM); + + // *testout << "recv exchange edges: " << recv_edges << endl; + + for (int sender = 1; sender < ntasks; sender ++) + if (id != sender) + { + FlatArray<int> recvarray = recv_edges[sender-1]; + + for (int ii = 0; ii < recvarray.Size(); ) + { + int globe = recvarray[ii++]; + int diste = recvarray[ii++]; + + if (globe <= maxedge) + { + int loce = glob2loc[globe]; + if (loce != -1) + SetDistantEdgeNum (sender, loce, diste); + } + } + } + + + + NgProfiler::StopTimer (timere); + + + MPI_Barrier (MPI_HIGHORDER_COMM); + + if (mesh.GetDimension() == 3) + { + + NgProfiler::StartTimer (timerf); + + glob2loc.SetSize (nfaglob); + glob2loc = -1; + + for (int loc = 1; loc <= nfa; loc++) + glob2loc[GetDistantFaceNum(0, loc)] = loc; + + cnt_send = 0; + Array<int> 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<int> 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, GetDistantFaceNum(0, face)); + send_faces.Add (dest-1, face); + } + } + } + TABLE<int> recv_faces(ntasks-1); + MyMPI_ExchangeTable (send_faces, recv_faces, MPI_TAG_MESH+8, MPI_HIGHORDER_COMM); + + // *testout << "send exchange faces: " << send_faces << endl; + // *testout << "recv exchange faces: " << recv_faces << endl; + + for (int sender = 1; sender < ntasks; sender ++) + if (id != sender) + { + FlatArray<int> recvarray = recv_faces[sender-1]; + + for (int ii = 0; ii < recvarray.Size(); ) + { + int globf = recvarray[ii++]; + int distf = recvarray[ii++]; + int locf = glob2loc[globf]; + + // *testout << "set distant face, sender = " << sender << ", locf = " << locf << "; distf = " << distf << endl; + if (locf != -1) + SetDistantFaceNum (sender, locf, distf); + } + } + + + NgProfiler::StopTimer (timerf); + } + + + // set which elements are where for the master processor + + coarseupdate = 1; + } + + + + + + void ParallelMeshTopology :: UpdateTopology () + { + ; + } + + + + + + + + void ParallelMeshTopology :: SetNV ( const int anv ) + { + *testout << "called setnv" << endl + << "old size: " << loc2distvert.Size() << endl + << "new size: " << anv << endl; + + loc2distvert.ChangeSize (anv); + for (int i = 1; i <= anv; i++) + if (loc2distvert.EntrySize(i) == 0) + loc2distvert.Add (i, -1); // will be the global nr + + nv = anv; + } + + void ParallelMeshTopology :: SetNE ( const int ane ) + { + loc2distel.ChangeSize (ane); + for (int i = 0; i < ane; i++) + if (loc2distel[i].Size() == 0) + loc2distel.Add (i, -1); // will be the global nr + ne = ane; + } + + void ParallelMeshTopology :: SetNSE ( int anse ) + { + loc2distsurfel.ChangeSize (anse); + for (int i = 0; i < anse; i++) + if (loc2distsurfel[i].Size() == 0) + loc2distsurfel.Add (i, -1); // will be the global nr + + nsurfel = anse; + } + + void ParallelMeshTopology :: SetNSegm ( int anseg ) + { + loc2distsegm.ChangeSize (anseg); + for (int i = 0; i < anseg; i++) + if (loc2distsegm[i].Size() == 0) + loc2distsegm.Add (i, -1); // will be the global nr + + nseg = anseg; + } + + +} + + + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/paralleltop.hpp b/contrib/Netgen/libsrc/meshing/paralleltop.hpp new file mode 100644 index 0000000000..52c03c5225 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/paralleltop.hpp @@ -0,0 +1,156 @@ +#ifndef FILE_PARALLELTOP +#define FILE_PARALLELTOP + +namespace netgen +{ + + // extern int ntasks; + + class ParallelMeshTopology + { + const Mesh & mesh; + + // number of local elements, vertices, points (?), edges, faces + int ne, nv, np, ned, nfa; + + // number of local segments and surface elements + int nseg, nsurfel; + + // number of global elements, vertices, ???, faces + int neglob, nseglob, nvglob; + int nparel; + int nfaglob; + int nedglob; + + /** + 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<int,PointIndex::BASE> loc2distvert; + TABLE<int,0> loc2distedge, loc2distface; + TABLE<int,0> loc2distel, loc2distsegm, loc2distsurfel; + + bool coarseupdate; + + public: + + ParallelMeshTopology (const Mesh & amesh); + ~ParallelMeshTopology (); + + /// 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 SetNVGlob ( int anvglob ) { nvglob = anvglob; } + void SetNEGlob ( int aneglob ) { neglob = aneglob; } + void SetNSEGlob ( int anseglob ) { nseglob = anseglob; } + + int GetNVGlob () { return nvglob; } + int GetNEGlob () { return neglob; } + + + void Reset (); + + void SetLoc2Glob_Vert ( int locnum, int globnum ) { loc2distvert[locnum][0] = globnum; } + void SetLoc2Glob_VolEl ( int locnum, int globnum ) { loc2distel[locnum-1][0] = globnum; } + void SetLoc2Glob_SurfEl ( int locnum, int globnum ) { loc2distsurfel[locnum-1][0] = globnum; } + void SetLoc2Glob_Segm ( int locnum, int globnum ) { loc2distsegm[locnum-1][0] = globnum; } + + int GetLoc2Glob_Vert ( int locnum ) const { return loc2distvert[locnum][0]; } + int GetLoc2Glob_VolEl ( int locnum ) const { return loc2distel[locnum-1][0]; } + int GetLoc2Glob_SurfEl ( int locnum ) const { return loc2distsurfel[locnum-1][0]; } + + void GetVertNeighbours ( int vnum, Array<int> & dests ) const; + + + int GetNDistantPNums ( int locpnum ) const + { return loc2distvert[locpnum].Size() / 2 + 1; } + + int GetNDistantFaceNums ( int locfacenum ) const + { return loc2distface[locfacenum-1].Size() / 2 + 1; } + + int GetNDistantEdgeNums ( int locedgenum ) const + { return loc2distedge[locedgenum-1].Size() / 2 + 1; } + + int GetNDistantElNums ( int locelnum ) const + { return loc2distel[locelnum-1].Size() / 2 + 1; } + + int GetDistantPNum ( int proc, int locpnum ) const; + int GetDistantEdgeNum ( int proc, int locedgenum ) const; + int GetDistantFaceNum ( int proc, int locedgenum ) const; + int GetDistantElNum ( int proc, int locelnum ) const; + + int GetDistantPNums ( int locpnum, int * distpnums ) const; + int GetDistantEdgeNums ( int locedgenum, int * distedgenums ) const; + int GetDistantFaceNums ( int locedgenum, int * distfacenums ) const; + int GetDistantElNums ( int locelnum, int * distfacenums ) const; + + void Print() const; + + + bool IsExchangeVert ( PointIndex vnum ) const { return loc2distvert[vnum].Size() > 1; } + bool IsExchangeEdge ( int ednum ) const { return loc2distedge[ednum-1].Size() > 1; } + bool IsExchangeFace ( int fnum ) const { return loc2distface[fnum-1].Size() > 1; } + bool IsExchangeElement ( int elnum ) const { return false; } + + + bool IsExchangeSEl ( int selnum ) const { return loc2distsurfel[selnum-1].Size() > 1; } + + + bool IsExchangeVert (int dest, int vnum ) const + { + FlatArray<int> exchange = loc2distvert[vnum]; + for (int i = 1; i < exchange.Size(); i += 2) + if (exchange[i] == dest) return true; + return false; + } + + bool IsExchangeEdge (int dest, int ednum ) const + { + FlatArray<int> exchange = loc2distedge[ednum-1]; + for (int i = 1; i < exchange.Size(); i += 2) + if (exchange[i] == dest) return true; + return false; + } + + bool IsExchangeFace (int dest, int fnum ) const + { + FlatArray<int> exchange = loc2distface[fnum-1]; + for (int i = 1; i < exchange.Size(); i += 2) + if (exchange[i] == dest) return true; + return false; + } + + bool IsExchangeElement (int dest, int elnum ) const { return false; } + + void Update(); + + void UpdateCoarseGrid(); + void UpdateRefinement (); + void UpdateTopology (); + void UpdateExchangeElements(); + + void UpdateCoarseGridGlobal(); + + bool DoCoarseUpdate() const { return !coarseupdate; } + + void SetDistantFaceNum ( int dest, int locnum, int distnum ); + void SetDistantPNum ( int dest, int locnum, int distnum ); + void SetDistantEdgeNum ( int dest, int locnum, int distnum ); + void SetDistantEl ( int dest, int locnum, int distnum ); + void SetDistantSurfEl ( int dest, int locnum, int distnum ); + void SetDistantSegm ( int dest, int locnum, int distnum ); + + bool IsGhostEl ( int elnum ) const { return mesh.VolumeElement(elnum).IsGhost(); } + }; + + +} + + + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/parser2.cpp b/contrib/Netgen/libsrc/meshing/parser2.cpp new file mode 100644 index 0000000000..55bd1a5d6e --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/parser2.cpp @@ -0,0 +1,605 @@ +#include <mystdlib.h> +#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 \""<<ch<<"\""<< endl; + if (ch == '{') + { + ist >> 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<<"\""<< endl; + } + + ist >> ch; + //(*testout) << "read next character \""<<ch<<"\""<< endl; + } + + + ist.putback (ch); + } + + else if (strcmp (buf, "newpoints") == 0) + { + ist >> 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()); + + 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<int> 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<Point2d> (freezone.Size()); + Array<Point2d> & 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; i<tr1.size(); i++) + if(tr1[i] == ',') + tr1[i] = ':'; +#endif + + ist = new istringstream (tr1); + } + + + if (!ist->good()) + { + 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; +} + +} diff --git a/contrib/Netgen/libsrc/meshing/parser3.cpp b/contrib/Netgen/libsrc/meshing/parser3.cpp new file mode 100644 index 0000000000..c6ccba4a68 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/parser3.cpp @@ -0,0 +1,1019 @@ +#include <mystdlib.h> +#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<int> tr1(3); + Array<int> 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; + 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<int>); + + 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; // ',' + } + + /* + 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<int>); + 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<threeint>); + + Array<int> & freeset = *freesets.Elem(fs); + Array<threeint> & 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<int> 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<twoint>); + + // Array<int> & freeset = *freesets.Get(fs); + Array<twoint> & freesetedges = *freeedges.Last(); + Array<threeint> & 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; i<len; i++) + if(tr1[i] == ',') + tr1[i] = ':'; +#endif + + ist = new istringstream (tr1); + } + + if (!ist->good()) + { + 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; +} +} diff --git a/contrib/Netgen/libsrc/meshing/prism2rls.cpp b/contrib/Netgen/libsrc/meshing/prism2rls.cpp new file mode 100644 index 0000000000..7e696554c0 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/prism2rls.cpp @@ -0,0 +1,457 @@ +namespace 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}; +} diff --git a/contrib/Netgen/libsrc/meshing/prism2rls_2.cpp b/contrib/Netgen/libsrc/meshing/prism2rls_2.cpp new file mode 100644 index 0000000000..baf0bef388 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/prism2rls_2.cpp @@ -0,0 +1,446 @@ +namespace 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}; +} diff --git a/contrib/Netgen/libsrc/meshing/pyramid2rls.cpp b/contrib/Netgen/libsrc/meshing/pyramid2rls.cpp new file mode 100644 index 0000000000..a97e7f13e5 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/pyramid2rls.cpp @@ -0,0 +1,309 @@ +namespace 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}; +} diff --git a/contrib/Netgen/libsrc/meshing/pyramidrls.cpp b/contrib/Netgen/libsrc/meshing/pyramidrls.cpp new file mode 100644 index 0000000000..d4e997c1fe --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/pyramidrls.cpp @@ -0,0 +1,263 @@ +namespace 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}; +} diff --git a/contrib/Netgen/libsrc/meshing/quadrls.cpp b/contrib/Netgen/libsrc/meshing/quadrls.cpp new file mode 100644 index 0000000000..1c2cd23b77 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/quadrls.cpp @@ -0,0 +1,887 @@ +namespace 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}; +} diff --git a/contrib/Netgen/libsrc/meshing/refine.cpp b/contrib/Netgen/libsrc/meshing/refine.cpp new file mode 100644 index 0000000000..403e45325b --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/refine.cpp @@ -0,0 +1,757 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + + void Refinement :: Refine (Mesh & mesh) const + { + const_cast<Refinement&> (*this).Refine(mesh); + } + + + void Refinement :: Refine (Mesh & mesh) + { + // reduce 2nd order + mesh.ComputeNVertices(); + mesh.SetNP(mesh.GetNV()); + + + INDEX_2_HASHTABLE<int> between(mesh.GetNP() + 5); + + int oldne, oldns, oldnf; + + // refine edges + + Array<EdgePointGeomInfo,PointIndex::BASE> epgi; + + 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; + EdgePointGeomInfo ngi; + + if (between.Used(i2)) + { + pinew = between.Get(i2); + ngi = epgi[pinew]; + } + else + { + 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); + 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); + } + + // refine surface elements + Array<PointGeomInfo,PointIndex::BASE> surfgi (8*mesh.GetNP()); + for (int i = PointIndex::BASE; + i < surfgi.Size()+PointIndex::BASE; i++) + surfgi[i].trignum = -1; + + + oldnf = mesh.GetNSE(); + for (SurfaceElementIndex sei = 0; sei < oldnf; sei++) + { + int j, k; + const Element2d & el = mesh.SurfaceElement(sei); + + switch (el.GetType()) + { + case TRIG: + case TRIG6: + { + ArrayMem<int,6> pnums(6); + ArrayMem<PointGeomInfo,6> pgis(6); + + static int betw[3][3] = + { { 2, 3, 4 }, + { 1, 3, 5 }, + { 1, 2, 6 } }; + + for (j = 1; j <= 3; j++) + { + pnums.Elem(j) = el.PNum(j); + pgis.Elem(j) = el.GeomInfoPi(j); + } + + for (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; + 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 (j = 0; j < 4; j++) + { + Element2d nel(TRIG); + for (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<int,9> pnums(9); + ArrayMem<PointGeomInfo,9> pgis(9); + + static int betw[5][3] = + { { 1, 2, 5 }, + { 2, 3, 6 }, + { 3, 4, 7 }, + { 1, 4, 8 }, + { 5, 7, 9 } }; + + for (j = 1; j <= 4; j++) + { + pnums.Elem(j) = el.PNum(j); + pgis.Elem(j) = el.GeomInfoPi(j); + } + + for (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 (j = 0; j < 4; j++) + { + Element2d nel(QUAD); + for (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())); + } + } + + // refine volume elements + oldne = mesh.GetNE(); + for (ElementIndex ei = 0; ei < oldne; ei++) + { + int j, k; + + const Element & el = mesh.VolumeElement(ei); + switch (el.GetType()) + { + case TET: + case TET10: + { + ArrayMem<int,10> 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 (j = 1; j <= 4; j++) + pnums.Elem(j) = el.PNum(j); + if (elrev) + swap (pnums.Elem(3), pnums.Elem(4)); + + for (j = 0; j < 6; 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(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)); + } + } + + 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 (j = 0; j < 8; j++) + { + Element nel; + for (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<int,27> 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 }, + }; + */ + + // udpated 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 = -1; + + for (j = 1; j <= 8; j++) + pnums.Elem(j) = el.PNum(j); + + + for (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 (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 (j = 0; j < 8; j++) + { + Element nel(HEX); + for (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<int,18> 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 = -1; + + for (j = 1; j <= 6; j++) + pnums.Elem(j) = el.PNum(j); + // if (elrev) + // swap (pnums.Elem(3), pnums.Elem(4)); + + for (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 (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 (j = 0; j < 8; j++) + { + Element nel(PRISM); + for (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<int,PointIndex::BASE> 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; + 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.ComputeNVertices(); + mesh.RebuildSurfaceElementLists(); + 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<Point<3> > should(np); + Array<Point<3> > 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; + int 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 (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)); + } + + + 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 (int i = 1; i <= mesh.GetNSE(); i++) + for (int j = 1; j <= 3; j++) + (*testout) << mesh.SurfaceElement(i).PNum(j) << 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(); + } +} diff --git a/contrib/Netgen/libsrc/meshing/ruler2.cpp b/contrib/Netgen/libsrc/meshing/ruler2.cpp new file mode 100644 index 0000000000..62058d2ed2 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/ruler2.cpp @@ -0,0 +1,719 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + + + static double CalcElementBadness (const Array<Point2d> & 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<Point2d> & lpoints, + Array<int> & legalpoints, + int maxlegalpoint, + Array<INDEX_2> & llines1, + int maxlegalline, + Array<Element2d> & elements, + Array<INDEX> & 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<int,100> pused(maxlegalpoint), lused(maxlegalline); + ArrayMem<int,100> pnearness(noldlp), lnearness(llines1.Size()); + + ArrayMem<int, 20> pmap, pfixed, lmap; + + ArrayMem<Point2d,100> tempnewpoints; + ArrayMem<INDEX_2,100> tempnewlines; + ArrayMem<int,100> tempdellines; + ArrayMem<Element2d,100> 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<INDEX_2> llines(llines1.Size()); + Array<int> 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); + + pmap.Elem(i) = lpoints.Append (np); + } + } + + // 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; + } + + + + + +} diff --git a/contrib/Netgen/libsrc/meshing/ruler2.hpp b/contrib/Netgen/libsrc/meshing/ruler2.hpp new file mode 100644 index 0000000000..afbe6b985a --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/ruler2.hpp @@ -0,0 +1,169 @@ +#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<Point2d> points; + /// + Array<INDEX_2> lines; + /// + Array<Point2d> freezone, freezonelimit; + /// + Array<Array<Point2d>*> freezone_i; + /// + Array<Point2d> transfreezone; + + /// + Array<int> dellines; + /// + Array<Element2d> elements; + /// + Array<threefloat> tolerances, linetolerances; + /// + Array<threeint> orientations; + /// + DenseMatrix oldutonewu, oldutofreearea, oldutofreearealimit; + /// + Array<DenseMatrix*> oldutofreearea_i; + /// + MatrixFixWidth<3> freesetinequ; + + /// + Array<Vec2d> linevecs; + + /// + int noldp, noldl; + /// + float fzminx, fzmaxx, fzminy, fzmaxy; + + /// topological distance of line to base element + Array<int> 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<int> & GetDelLines() const { return dellines; } + /// + void GetFreeZone (Array<Point2d> & 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<Point2d> & 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 + diff --git a/contrib/Netgen/libsrc/meshing/ruler3.cpp b/contrib/Netgen/libsrc/meshing/ruler3.cpp new file mode 100644 index 0000000000..3b6f7a91ac --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/ruler3.cpp @@ -0,0 +1,1136 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ +extern double minother; +extern double minwithoutother; + + +static double CalcElementBadness (const Array<Point3d> & points, + const Element & elem) +{ + double vol, l, l4, l5, l6; + if (elem.GetNP() != 4) + { + if (elem.GetNP() == 5) + { + double z = points.Get(elem.PNum(5)).Z(); + if (z > -1e-8) return 1e8; + return (-1 / z) - z; // - 2; + } + return 0; + } + + Vec3d v1 = points.Get(elem.PNum(2)) - points.Get(elem.PNum(1)); + Vec3d v2 = points.Get(elem.PNum(3)) - points.Get(elem.PNum(1)); + Vec3d v3 = points.Get(elem.PNum(4)) - points.Get(elem.PNum(1)); + + vol = - (Cross (v1, v2) * v3); + l4 = Dist (points.Get(elem.PNum(2)), points.Get(elem.PNum(3))); + l5 = Dist (points.Get(elem.PNum(2)), points.Get(elem.PNum(4))); + l6 = Dist (points.Get(elem.PNum(3)), points.Get(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<Point3d> & lpoints, // in: local points, out: old+new local points + Array<int> & allowpoint, // in: 2 .. it is allowed to use pointi, 1..will be allowed later, 0..no means + Array<MiniElement2d> & lfaces, // in: local faces, out: old+new local faces + INDEX lfacesplit, // for local faces in outer radius + INDEX_2_HASHTABLE<int> & connectedpairs, // connected pairs for prism-meshing + Array<Element> & elements, // out: new elements + Array<INDEX> & 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 + ) + +{ + NgProfiler::RegionTimer regtot(97); + + int i, j, k, ri, nfok, npok, incnpok, refpi, locpi, locfi, locfr; + float hf, err, minerr, teterr, minteterr; + char ok, found, hc; + vnetrule * rule; + Vector oldu, newu, newu1, newu2, allp; + Vec3d ui; + Point3d np; + int oldnp, noldlp, noldlf; + const MiniElement2d * locface = NULL; + int loktestmode; + + + Array<int> pused; // point is already mapped + Array<char> fused; // face is already mapped + Array<int> pmap; // map of reference point to local point + Array<char> pfixed; // point mapped by face-map + Array<int> fmapi; // face in reference is mapped to face nr ... + Array<int> fmapr; // face in reference is rotated to map + Array<Point3d> transfreezone; // transformed free-zone + INDEX_2_CLOSED_HASHTABLE<int> ledges(100); // edges in local environment + + Array<Point3d> tempnewpoints; + Array<MiniElement2d> tempnewfaces; + Array<int> tempdelfaces; + Array<Element> tempelements; + Array<Box3d> triboxes; // bounding boxes of local faces + + Array<int, PointIndex::BASE> pnearness; + Array<int> 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 (j = 0; j < lfaces[0].GetNP(); j++) + pnearness[lfaces[0][j]] = 0; + + NgProfiler::RegionTimer reg2(98); + + NgProfiler::StartTimer (90); + + for (int loop = 0; loop < 2; loop++) + { + + for (i = 0; i < lfacesplit; i++) + { + const MiniElement2d & hface = lfaces[i]; + + int minn = INT_MAX-1; + for (j = 0; j < hface.GetNP(); j++) + { + int hi = pnearness[hface[j]]; + if (hi < minn) minn = hi; + } + if (minn < INT_MAX/10) + for (j = 0; j < hface.GetNP(); j++) + if (pnearness[hface[j]] > minn+1) + pnearness[hface[j]] = minn+1; + } + + for (i = 1; i <= connectedpairs.GetNBags(); i++) + for (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 (i = 0; i < fnearness.Size(); i++) + { + int sum = 0; + for (j = 0; j < lfaces[i].GetNP(); j++) + sum += pnearness[lfaces[i][j]]; + fnearness[i] = sum; + } + + + NgProfiler::StopTimer (90); + NgProfiler::StartTimer (91); + + // find bounding boxes of faces + + triboxes.SetSize (lfaces.Size()); + for (i = 0; i < lfaces.Size(); i++) + { + const MiniElement2d & face = lfaces[i]; + triboxes[i].SetPoint (lpoints.Get(face[0])); + for (j = 1; j < face.GetNP(); j++) + triboxes[i].AddPoint (lpoints.Get(face[j])); + } + + NgProfiler::StopTimer (91); + NgProfiler::StartTimer (92); + + + bool useedges = 0; + for (ri = 0; ri < rules.Size(); ri++) + if (rules[ri]->GetNEd()) useedges = 1; + + if (useedges) + { + ledges.SetSize (5 * lfacesplit); + + for (j = 0; j < lfacesplit; j++) + // if (fnearness[j] <= 5) + { + const MiniElement2d & face = lfaces[j]; + int newp, oldp; + + newp = face[face.GetNP()-1]; + for (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: + + for (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), ""); + + 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; + pmap = 0; + fmapi = 0; + for (i = 1; i <= fmapr.Size(); i++) + fmapr.Set(i, rule->GetNP(i)); + + fused[0] = 1; + fmapi[0] = 1; + fmapr[0] = rotind1; + + + for (j = 1; j <= lfaces.Get(1).GetNP(); j++) + { + locpi = lfaces[0].PNumMod (j+rotind1); + pmap.Set (rule->GetPointNr (1, j), locpi); + pused.Elem(locpi)++; + } + + /* + map all faces + nfok .. first nfok-1 faces are mapped properly + */ + + 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; + locfi = fmapi.Get(nfok); + 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 (j = 1; j <= actfnp && ok; j++) + { + locpi = pmap.Get(rule->GetPointNr (nfok, j)); + + if (locpi && locpi != locface->PNumMod(j+locfr)) + ok = 0; + } + + // local point already used or point outside tolerance ? + for (j = 1; j <= actfnp && ok; j++) + { + refpi = rule->GetPointNr (nfok, j); + + if (pmap.Get(refpi) == 0) + { + locpi = locface->PNumMod (j + locfr); + + if (pused.Get(locpi)) + ok = 0; + else + { + const Point3d & lp = lpoints.Get(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 (j = 1; j <= rule->GetNP (nfok); j++) + { + 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.Elem(locpi)++; + } + + nfok++; + } + else + { + // backtrack one face + fmapi.Set (nfok, 0); + fmapr.Set (nfok, rule->GetNP(nfok)); + nfok--; + + fused.Set (fmapi.Get(nfok), 0); + for (j = 1; j <= rule->GetNP (nfok); j++) + { + refpi = rule->GetPointNr (nfok, j); + pused.Elem(pmap.Get(refpi))--; + + if (pused.Get(pmap.Get(refpi)) == 0) + { + pmap.Set(refpi, 0); + } + } + } + } + + 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"); + } + + npok = 1; + incnpok = 1; + + pfixed.SetSize (pmap.Size()); + for (i = 1; i <= pmap.Size(); i++) + pfixed.Set(i, (pmap.Get(i) != 0) ); + + while (npok >= 1) + { + + if (npok <= rule->GetNOldP()) + { + + if (pfixed.Get(npok)) + + { + if (incnpok) + npok++; + else + npok--; + } + + else + + { + locpi = pmap.Elem(npok); + ok = 0; + + if (locpi) + pused.Elem(locpi)--; + + while (!ok && locpi < lpoints.Size()) + { + ok = 1; + locpi++; + + if (pused.Get(locpi) || + pnearness.Get(locpi) > rule->GetPNearness(npok)) + { + ok = 0; + } + else if (allowpoint.Get(locpi) != 2) + { + ok = 0; + if (allowpoint.Get(locpi) == 1) + impossible = 0; + } + else + { + const Point3d & lp = lpoints.Get(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.Elem(locpi)++; + npok++; + incnpok = 1; + } + + else + + { + pmap.Set (npok, 0); + + 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 (i = 1; i <= pmap.Size(); i++) + (*testout) << pmap.Get(i) << " "; + (*testout) << endl; + sprintf (problems.Elem(ri), "mapping found"); + (*testout) << rule->GetNP(1) << " = " << lfaces.Get(1).GetNP() << endl; + } + + ok = 1; + + + // check mapedges: + for (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 (i = 1; i <= rule->GetNE(); i++) + { + const Element & el = rule->GetElement (i); + if (el.GetType() == PRISM) + { + for (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 (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 (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 (i = 1; i <= rule->GetNOldP(); i++) + { + const Point3d & lp = lpoints.Get(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 (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<Point3d> & fz = rule->GetTransFreeZone(); + (*testout) << "Freezone: " << endl; + for (i = 1; i <= fz.Size(); i++) + (*testout) << fz.Get(i) << endl; + } + + + // check freezone: + + for (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 (i = 1; i <= lfaces.Size() && ok; i++) + { + static Array<int> 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; + int 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.Get(lfacei.PNum(1)), + lpoints.Get(lfacei.PNum(2)), + lpoints.Get(lfacei.PNum(3)), lpi, 1 + ); + } + else + { + triin = rule->IsQuadInFreeZone + ( + lpoints.Get(lfacei.PNum(1)), + lpoints.Get(lfacei.PNum(2)), + lpoints.Get(lfacei.PNum(3)), + lpoints.Get(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.Get(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.Get(lfacei.PNum(1)) << " - " + << lpoints.Get(lfacei.PNum(2)) << " - " + << lpoints.Get(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.Get(lfacei.PNum(1)) << " - " + << lpoints.Get(lfacei.PNum(2)) << " - " + << lpoints.Get(lfacei.PNum(3)) << " - " + << lpoints.Get(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 (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 (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 (i = 1; i <= rule->GetNOldP(); i++) + { + hf = rule->CalcPointDist (i, lpoints.Get(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: + + oldnp = rule->GetNOldP(); + noldlp = lpoints.Size(); + noldlf = lfaces.Size(); + + + for (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); + + pmap.Elem(i) = lpoints.Append (np); + } + + // Set new Faces: + + for (i = rule->GetNOldF() + 1; i <= rule->GetNF(); i++) + if (!fmapi.Get(i)) + { + MiniElement2d nface(rule->GetNP(i)); + for (j = 1; j <= nface.GetNP(); j++) + nface.PNum(j) = pmap.Get(rule->GetPointNr (i, j)); + + lfaces.Append (nface); + } + + + // Delete old Faces: + + for (i = 1; i <= rule->GetNDelF(); i++) + delfaces.Append (fmapi.Get(rule->GetDelFace(i))); + for (i = rule->GetNOldF()+1; i <= rule->GetNF(); i++) + if (fmapi.Get(i)) + { + delfaces.Append (fmapi.Get(i)); + fmapi.Elem(i) = 0; + } + + + // check orientation + for (i = 1; i <= rule->GetNO() && ok; i++) + { + const fourint * fouri; + + fouri = &rule->GetOrientation(i); + Vec3d v1 (lpoints.Get(pmap.Get(fouri->i1)), + lpoints.Get(pmap.Get(fouri->i2))); + Vec3d v2 (lpoints.Get(pmap.Get(fouri->i1)), + lpoints.Get(pmap.Get(fouri->i3))); + Vec3d v3 (lpoints.Get(pmap.Get(fouri->i1)), + lpoints.Get(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 (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 (i = 1; i <= rule->GetNE(); i++) + { + elements.Append (rule->GetElement(i)); + for (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 (i = 1; i <= elements.Size(); i++) + { + 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 (i = 1; i <= rule->GetNDelF(); i++) + { + const Element2d & face = + rule->GetFace (rule->GetDelFace(i)); + for (j = 1; j <= 3; j++) + { + const Point3d & p1 = + lpoints.Get(pmap.Get(face.PNumMod(j))); + const Point3d & p2 = + lpoints.Get(pmap.Get(face.PNumMod(j+1))); + oldlen += Dist(p1, p2); + } + } + + for (i = rule->GetNOldF()+1; i <= rule->GetNF(); i++) + { + const Element2d & face = rule->GetFace (i); + for (j = 1; j <= 3; j++) + { + const Point3d & p1 = + lpoints.Get(pmap.Get(face.PNumMod(j))); + const Point3d & p2 = + lpoints.Get(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 (i = 1; i <= rule->GetNOldP(); i++) + { + (*testout) << "P" << i << ": Ref: " + << rule->GetPoint (i) << " is: " + << lpoints.Get(pmap.Get(i)) << endl; + } + } + + tempnewpoints.SetSize (0); + for (i = noldlp+1; i <= lpoints.Size(); i++) + tempnewpoints.Append (lpoints.Get(i)); + + tempnewfaces.SetSize (0); + for (i = noldlf+1; i <= lfaces.Size(); i++) + tempnewfaces.Append (lfaces.Get(i)); + + tempdelfaces.SetSize (0); + for (i = 1; i <= delfaces.Size(); i++) + tempdelfaces.Append (delfaces.Get(i)); + + tempelements.SetSize (0); + for (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 (j = 1; j <= rule->GetNP (nfok); j++) + { + refpi = rule->GetPointNr (nfok, j); + pused.Elem(pmap.Get(refpi))--; + + if (pused.Get(pmap.Get(refpi)) == 0) + { + pmap.Set(refpi, 0); + } + } + + } + } + if (loktestmode) + (*testout) << "end rule" << endl; + } + + if (found) + { + for (i = 1; i <= tempnewpoints.Size(); i++) + lpoints.Append (tempnewpoints.Get(i)); + for (i = 1; i <= tempnewfaces.Size(); i++) + if (tempnewfaces.Get(i).PNum(1)) + lfaces.Append (tempnewfaces.Get(i)); + for (i = 1; i <= tempdelfaces.Size(); i++) + delfaces.Append (tempdelfaces.Get(i)); + for (i = 1; i <= tempelements.Size(); i++) + elements.Append (tempelements.Get(i)); + } + + retminerr = minerr; + + + if (impossible && found == 0) + return -1; + + return found; +} +} diff --git a/contrib/Netgen/libsrc/meshing/ruler3.hpp b/contrib/Netgen/libsrc/meshing/ruler3.hpp new file mode 100644 index 0000000000..fcbf8f5990 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/ruler3.hpp @@ -0,0 +1,210 @@ +#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<Point3d> points; + /// old and new faces in reference numbering + Array<Element2d> faces; + /// additional edges of rule + Array<twoint> edges; + + /// points of freezone in reference coordinates + Array<Point3d> freezone; + /// points of freezone in reference coordinates if tolcalss to infty + Array<Point3d> freezonelimit; + /// point index, if point equal to mappoint, otherwise 0 + Array<int> freezonepi; + /// faces of each convex part of freezone + Array<Array<threeint>*> freefaces; + /// set of points of each convex part of freezone + Array<Array<int>*> freesets; + /// points of transformed freezone + Array<Point3d> transfreezone; + /// edges of each convex part of freezone + Array<Array<twoint>*> freeedges; + + /// face numbers to be deleted + Array<int> delfaces; + /// elements to be generated + Array<Element> elements; + /// tolerances for points and faces (used ??) + Array<double> 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<DenseMatrix*> freefaceinequ; + /// + Array<fourint> orientations; + /** + flags specified in rule-description file: + t .. test rule + */ + Array<char> flags; + + /** + topological distance of face to base element + non-connected: > 100 (??) + */ + Array<int> fnearness; + Array<int> 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<int> & pi, int newone); + /// + int IsQuadInFreeZone (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4, + const Array<int> & pi, int newone); + /// + int IsTriangleInFreeSet (const Point3d & p1, const Point3d & p2, + const Point3d & p3, int fs, const Array<int> & pi, int newone); + + /// + int IsQuadInFreeSet (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4, + int fs, const Array<int> & 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<Point3d> & GetTransFreeZone () { return transfreezone; } + /// + int TestOk () const; + + /// + friend void TestRules (); + /// + // friend void Plot3DRule (const ROT3D & r, char key); +}; + + + +#endif + diff --git a/contrib/Netgen/libsrc/meshing/secondorder.cpp b/contrib/Netgen/libsrc/meshing/secondorder.cpp new file mode 100644 index 0000000000..5b5b5d7f55 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/secondorder.cpp @@ -0,0 +1,490 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + + void Refinement :: MakeSecondOrder (Mesh & mesh) const + { + const_cast<Refinement&> (*this).MakeSecondOrder(mesh); + } + + + void Refinement :: MakeSecondOrder (Mesh & mesh) + { + int nseg, nse, ne; + + mesh.ComputeNVertices(); + mesh.SetNP(mesh.GetNV()); + + INDEX_2_HASHTABLE<int> between(mesh.GetNP() + 5); + + + bool thinlayers = 0; + for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) + if (mesh[ei].GetType() == PRISM || + mesh[ei].GetType() == PRISM12) + thinlayers = 1; + + + 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); + between.Set (i2, el[2]); + } + } + + // refine surface elements + nse = mesh.GetNSE(); + for (SurfaceElementIndex sei = 0; sei < nse; sei++) + { + int j; + const Element2d & el = mesh.SurfaceElement(sei); + + int onp(0); + + Element2d newel; + 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); + between.Set (i2, newel[onp+j]); + } + } + + mesh.SurfaceElement(sei) = newel; + } + + + // int i, j; + + + + // refine volume elements + ne = mesh.GetNE(); + for (int i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + int onp(0); + + Element newel; + 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 }, + }; + 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; + } + default: + PrintSysError ("MakeSecondOrder, illegal vol type ", 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()))); + 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<int,PointIndex::BASE> identmap; + mesh.GetIdentifications().GetMap (i, identmap); + + for (INDEX_2_HASHTABLE<int>::Iterator it = between.Begin(); + it != between.End(); it++) + { + INDEX_2 i2; + int newpi; + between.GetData (it, 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); + } + } + + /* + 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<int>::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<INDEX_2> 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<INDEX_2> & 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<Point<3> > should(np); + Array<Point<3> > 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; + } + */ + } + +} diff --git a/contrib/Netgen/libsrc/meshing/smoothing2.5.cpp b/contrib/Netgen/libsrc/meshing/smoothing2.5.cpp new file mode 100644 index 0000000000..c9de8e2144 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/smoothing2.5.cpp @@ -0,0 +1,265 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#include <opti.hpp> + +namespace netgen +{ + + + void MeshOptimize2d :: ProjectBoundaryPoints(Array<int> & surfaceindex, + const Array<Point<3>* > & from, Array<Point<3>* > & dest) + { + for(int i=0; i<surfaceindex.Size(); i++) + { + if(surfaceindex[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<SurfaceElementIndex> 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<MeshPoint, PointIndex::BASE> savepoints(mesh.GetNP()); + + Array<int, PointIndex::BASE> 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<SurfaceElementIndex,PointIndex::BASE> 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<SurfaceElementIndex> locelements(0); + Array<int> locrots(0); + + for (PointIndex pi = PointIndex::BASE; + pi < mesh.GetNP()+PointIndex::BASE; 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(); + } + + +} diff --git a/contrib/Netgen/libsrc/meshing/smoothing2.cpp b/contrib/Netgen/libsrc/meshing/smoothing2.cpp new file mode 100644 index 0000000000..fe47f8b88d --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/smoothing2.cpp @@ -0,0 +1,903 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#include <opti.hpp> + +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 Point3d & p1, + const Point3d & p2, + const Point3d & p3, + double metricweight, + double h) + { + // badness = sqrt(3.0) / 12 * (\sum l_i^2) / area - 1 + // p1 = (0, 0), p2 = (x2, 0), p3 = (x3, y3); + + Vec3d e12(p1,p2); + Vec3d e13(p1,p3); + Vec3d e23(p2,p3); + + double l12_2 = e12.Length2(); + double l13_2 = e13.Length2(); + double l23_2 = e23.Length2(); + + double cir_2 = l12_2 + l13_2 + l23_2; + Vec3d area_v = Cross (e12, e13); + double area = 0.5 * area_v.Length(); + + if (area <= 1e-24 * cir_2) + return 1e10; + + double badness = c_trig * cir_2 / area - 1; + + if (metricweight > 0) + { + // area = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1); + // add: metricweight * (area / h^2 + h^2 / area - 2) + + const double areahh = area / (h * h); + badness += metricweight * (areahh + 1 / areahh - 2); + } + + return badness; + } + + + double CalcTriangleBadness (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + const Vec3d & n, + double metricweight, + double h) + { + Vec3d v1 (p1, p2); + Vec3d v2 (p1, p3); + + Vec3d e1 = v1; + Vec3d 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<SurfaceElementIndex> locelements; + Array<int> locrots; + Array<double> lochs; + // 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 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 Opti2SurfaceMinFunction :: + Func (const Vector & x) const + { + Vector g(x.Size()); + return FuncGrad (x, g); + } + + + double Opti2SurfaceMinFunction :: + FuncGrad (const Vector & x, Vector & grad) const + { + Vec<3> n, vgrad; + Point<3> pp1; + double g1x, g1y; + double badness, hbadness; + + 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); + + for (int j = 0; j < ld.locelements.Size(); j++) + { + 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; + + 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 :: + FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const + { + Vec<3> n, vgrad; + Point<3> pp1; + double g1x, g1y; + double badness, hbadness; + + 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; + + for (int j = 0; j < ld.locelements.Size(); j++) + { + 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; + + 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<Point2d> 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<Point2d> 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 int timer = NgProfiler::CreateTimer ("MeshSmoothing 2D"); + static int timer1 = NgProfiler::CreateTimer ("MeshSmoothing 2D start"); + + NgProfiler::RegionTimer reg (timer); + NgProfiler::StartTimer (timer1); + + CheckMeshApproximation (mesh); + + Opti2dLocalData ld; + + // SurfaceElementIndex sei; + + Array<SurfaceElementIndex> 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; + } + + int loci; + double fact; + int moveisok; + + PointGeomInfo ngi; + Point3d origp; + + + + Vec3d n1, n2; + Vector x(2), xedge(1); + + Array<MeshPoint, PointIndex::BASE> savepoints(mesh.GetNP()); + + ld.uselocalh = mp.uselocalh; + + + Array<int, PointIndex::BASE> 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<SurfaceElementIndex,PointIndex::BASE> 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; + + 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) + { + 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 = 10; + } + if (mesh.GetNP() > 10000) + { + plotchar = 'o'; + modplot = 100; + } + int cnt = 0; + + + NgProfiler::StopTimer (timer1); + + + for (PointIndex pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) + 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; + + + ld.sp1 = mesh[pi]; + + Element2d & hel = mesh[elementsonpoint[pi][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); + + for (int j = 0; j < elementsonpoint[pi].Size(); j++) + { + SurfaceElementIndex sei = elementsonpoint[pi][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); + 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 = ld.lochs[0]; + + if (mixed) + { + // (*testout) << "vorher : " << surfminfj.Func (x) << endl; + BFGS (x, surfminfj, par, 1e-6); + // (*testout) << "nachher: " << surfminfj.Func (x) << endl; + // (*testout) << "x = " << x << endl; + } + else + { + // (*testout) << "vorher : " << surfminf.Func (x) << endl; + BFGS (x, surfminf, par, 1e-6); + // (*testout) << "nachher: " << surfminf.Func (x) << endl; + // (*testout) << "x = " << x << endl; + } + + + origp = mesh[pi]; + loci = 1; + fact = 1; + 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]); + + 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); + } +} diff --git a/contrib/Netgen/libsrc/meshing/smoothing3.cpp b/contrib/Netgen/libsrc/meshing/smoothing3.cpp new file mode 100644 index 0000000000..bf2958848b --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/smoothing3.cpp @@ -0,0 +1,1838 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#ifdef SOLIDGEOM +#include <csg.hpp> +#endif +#include <opti.hpp> + + +namespace netgen +{ + + + double MinFunctionSum :: Func (const Vector & x) const + { + double retval = 0; + for(int i=0; i<functions.Size(); i++) + retval += functions[i]->Func(x); + + return retval; + } + + void MinFunctionSum :: Grad (const Vector & x, Vector & g) const + { + g = 0.; + VectorMem<3> gi; + for(int i=0; i<functions.Size(); i++) + { + functions[i]->Grad(x,gi); + for(int j=0; j<g.Size(); j++) + g[j] += gi[j]; + } + } + + + double MinFunctionSum :: FuncGrad (const Vector & x, Vector & g) const + { + double retval = 0; + g = 0.; + VectorMem<3> gi; + for(int i=0; i<functions.Size(); i++) + { + retval += functions[i]->FuncGrad(x,gi); + for(int j=0; j<g.Size(); j++) + g[j] += gi[j]; + } + return retval; + } + + double MinFunctionSum :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const + { + double retval = 0; + deriv = 0.; + double derivi; + for(int i=0; i<functions.Size(); i++) + { + retval += functions[i]->FuncDeriv(x,dir,derivi); + deriv += derivi; + } + return retval; + } + + double MinFunctionSum :: GradStopping (const Vector & x) const + { + double minfs(0), mini; + for(int i=0; i<functions.Size(); i++) + { + mini = functions[i]->GradStopping(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<INDEX_3> & 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[el.I1()], + points[el.I3()], + points[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<INDEX_3> & faces; + DenseMatrix m; + double h; + public: + CheapPointFunction1 (Mesh::T_POINTS & apoints, + const Array<INDEX_3> & 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<INDEX_3> & 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[faces.Get(i).I1()]; + const Point3d & p2 = points[faces.Get(i).I2()]; + const Point3d & p3 = points[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<int,PointIndex::BASE> elementsonpoint; + const MeshingParameters & mp; + PointIndex actpind; + double h; + + public: + PointFunction (Mesh::T_POINTS & apoints, + const Mesh::T_VOLELEMENTS & aelements, + const MeshingParameters & amp); + + 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<Element2d> 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; + 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; + int 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) +{ + 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<INDEX> 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 CSGeometry & 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<INDEX> 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) +{ + int typ = 1; + + (*testout) << "Improve Mesh" << "\n"; + PrintMessage (3, "ImproveMesh"); + + int np = GetNP(); + int ne = GetNE(); + + + Array<double,PointIndex::BASE> 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 (PointIndex i = PointIndex::BASE; i < np+PointIndex::BASE; 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<double, PointIndex::BASE> pointh (points.Size()); + + if(lochfunc) + { + for(int i=1; i<=points.Size(); i++) + pointh[i] = GetH(points.Get(i)); + } + else + { + pointh = 0; + for(int i=0; i<GetNE(); i++) + { + const Element & el = VolumeElement(i+1); + double h = pow(el.Volume(points),1./3.); + for(int j=1; j<=el.GetNV(); j++) + if(h > pointh[el.PNum(j)]) + pointh[el.PNum(j)] = 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 i = PointIndex::BASE; + i < points.Size()+PointIndex::BASE; i++) + if ( (*this)[i].Type() == INNERPOINT && perrs[i] > 0.01 * badmax) + { + if (multithread.terminate) + throw NgException ("Meshing stopped"); + + multithread.percent = 100.0 * (i+1-PointIndex::BASE) / points.Size(); + /* + if (points.Size() < 1000) + PrintDot (); + else + if ( (i+1-PointIndex::BASE) % 10 == 0) + PrintDot ('+'); + */ + if ( (i+1-PointIndex::BASE) % printmod == 0) PrintDot (printdot); + + double lh = pointh[i]; + pf->SetLocalH (lh); + par.typx = lh; + + freeminf.SetPoint (points[i]); + pf->SetPointIndex (i); + + x = 0; + int pok; + pok = freeminf.Func (x) < 1e10; + + if (!pok) + { + pok = pf->MovePointToInner (); + + freeminf.SetPoint (points[i]); + pf->SetPointIndex (i); + } + + if (pok) + { + //*testout << "start BFGS, pok" << endl; + BFGS (x, freeminf, par); + //*testout << "BFGS complete, pok" << endl; + points[i](0) += x(0); + points[i](1) += x(1); + points[i](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<double, PointIndex::BASE> 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<GetNE(); i++) + { + const Element & el = VolumeElement(i+1); + double h = pow(el.Volume(points),1./3.); + for(j=1; j<=el.GetNV(); j++) + if(h > pointh[el.PNum(j)]) + pointh[el.PNum(j)] = h; + } + } + + + + const char * savetask = multithread.task; + multithread.task = "Smooth Mesh Jacobian"; + + for (i = 1; i <= points.Size(); i++) + { + if ((*this)[PointIndex(i)].Type() != INNERPOINT) + continue; + + if(usepoint && !usepoint->Test(i)) + continue; + + //(*testout) << "improvejac, p = " << i << endl; + + if (goal == OPT_WORSTCASE && !badnodes.Test(i)) + continue; + // (*testout) << "smoot 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 (i); + + 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<int,PointIndex::BASE>* > * 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<int,PointIndex::BASE>* > locidmaps; + const Array< Array<int,PointIndex::BASE>* > * 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<int,PointIndex::BASE>); + 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<double, PointIndex::BASE> 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<GetNE(); i++) + { + const Element & el = VolumeElement(i+1); + double h = pow(el.Volume(points),1./3.); + for(j=1; j<=el.GetNV(); j++) + if(h > pointh[el.PNum(j)]) + pointh[el.PNum(j)] = h; + } + } + + + const char * savetask = multithread.task; + multithread.task = "Smooth Mesh Jacobian"; + + for (i = 1; i <= points.Size(); i++) + if ( usepoint.Test(i) ) + { + //(*testout) << "improvejac, p = " << i << endl; + + if (goal == OPT_WORSTCASE && !badnodes.Test(i)) + continue; + // (*testout) << "smoot 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 (i); + + int brother = -1; + if(usesum) + { + for(j=0; brother == -1 && j<used_idmaps->Size(); 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<locidmaps.Size(); i++) + delete locidmaps[i]; + + multithread.task = savetask; +} + + + + +} diff --git a/contrib/Netgen/libsrc/meshing/specials.cpp b/contrib/Netgen/libsrc/meshing/specials.cpp new file mode 100644 index 0000000000..0a218e10a6 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/specials.cpp @@ -0,0 +1,193 @@ +#include <mystdlib.h> +#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<Box3d> 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 (i = 1; i <= locked.Size(); i++) + if (locked.Test(i)) + { + mesh.AddLockedPoint (i); + } + + + + + Array<int> 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; + } +} +} diff --git a/contrib/Netgen/libsrc/meshing/specials.hpp b/contrib/Netgen/libsrc/meshing/specials.hpp new file mode 100644 index 0000000000..700ba4596b --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/specials.hpp @@ -0,0 +1,16 @@ +#ifndef FILE_SPECIALS +#define FILE_SPECIALS + +/* + + Very special implementations .. + + */ + + +/// +extern void CutOffAndCombine (Mesh & mesh, const Mesh & othermesh); + +extern void HelmholtzMesh (Mesh & mesh); + +#endif diff --git a/contrib/Netgen/libsrc/meshing/tetrarls.cpp b/contrib/Netgen/libsrc/meshing/tetrarls.cpp new file mode 100644 index 0000000000..cb28648b6a --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/tetrarls.cpp @@ -0,0 +1,1466 @@ +namespace netgen +{ +const char * tetrules[] = { +"tolfak 0.5\n",\ +"\n",\ +"rule \"Free Tetrahedron\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(0.5, 0.866, 0);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.288, -0.816)\n",\ +" { 0.333 X1, 0.333 X2, 0.333 X3 }\n",\ +" { 0.333 Y1, 0.333 Y2, 0.333 Y3 } { };\n",\ +"\n",\ +"newfaces\n",\ +"(4, 1, 2);\n",\ +"(4, 2, 3);\n",\ +"(4, 3, 1);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1.6 P4, -0.2 P1, -0.2 P2, -0.2 P3 };\n",\ +"{ -0.5 P1, 0.5 P2, 0.5 P3, 0.5 P4 };\n",\ +"{ 0.5 P1, -0.5 P2, 0.5 P3, 0.5 P4 };\n",\ +"{ 0.5 P1, 0.5 P2, -0.5 P3, 0.5 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 60\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"flags c;\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 } ;\n",\ +"(0.5, 0.866, 0) { 0.5 };\n",\ +"(0.5, 0.288, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(1, 4, 3);\n",\ +"(4, 2, 3);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ -0.05 P1, -0.05 P2, 0.7 P3, 0.4 P4 };\n",\ +"\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.65 P3, 0.35 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 60 with edge(1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"flags c;\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.8 };\n",\ +"(0.5, 0.866, 0) { 0.8 };\n",\ +"(0.5, 0.288, -0.816) { 0.8 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"mapedges\n",\ +"(3, 4);\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(1, 4, 3);\n",\ +"(4, 2, 3);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.4 P1, 0.4 P4, 0.4 P3, -0.2 P2 };\n",\ +"{ 0.4 P2, 0.4 P4, 0.4 P3, -0.2 P1 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P4, 0.3334 P3 };\n",\ +"{ 0.3333 P2, 0.3333 P4, 0.3334 P3 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron Vis a Vis Point (1)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 0.866, 0) { 0.5 };\n",\ +"(0.5, 0.288, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(4, 3, 1);\n",\ +"(4, 2, 3);\n",\ +"(4, 1, 2);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ -0.5 P1, 0.5 P2, 0.5 P3, 0.5 P4 };\n",\ +"{ 0.5 P1, -0.5 P2, 0.5 P3, 0.5 P4 };\n",\ +"{ 0.5 P1, 0.5 P2, -0.5 P3, 0.5 P4 };\n",\ +"{ 0.8 P1, -0.1 P2, -0.1 P3, 0.4 P4 };\n",\ +"{ -0.1 P1, 0.8 P2, -0.1 P3, 0.4 P4 };\n",\ +"{ -0.1 P1, -0.1 P2, 0.8 P3, 0.4 P4 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P2, 0.3334 P4 };\n",\ +"{ 0.7 P1, 0.3 P4 };\n",\ +"{ 0.7 P2, 0.3 P4 };\n",\ +"{ 0.7 P3, 0.3 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron Vis a Vis Point with edge(1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 0.866, 0) { 0.5 };\n",\ +"(0.5, 0.288, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"mapedges\n",\ +"(1, 4);\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(4, 3, 1);\n",\ +"(4, 2, 3);\n",\ +"(4, 1, 2);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, 0.45 P2, -0.35 P3, 0.45 P4 };\n",\ +"{ -0.05 P1, 0.7 P2, -0.05 P3, 0.4 P4 };\n",\ +"{ -0.05 P1, -0.05 P2, 0.7 P3, 0.4 P4 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P2, 0.3334 P4 };\n",\ +"{ 0.65 P2, 0.35 P4 };\n",\ +"{ 0.65 P3, 0.35 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron Vis a Vis Point with 2 edges (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 0.866, 0) { 0.5 };\n",\ +"(0.5, 0.288, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"mapedges\n",\ +"(1, 4);\n",\ +"(2, 4);\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(4, 3, 1);\n",\ +"(4, 2, 3);\n",\ +"(4, 1, 2);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, 0.45 P2, -0.35 P3, 0.45 P4 };\n",\ +"{ -0.05 P1, -0.05 P2, 0.7 P3, 0.4 P4 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P2, 0.3334 P4 };\n",\ +"{ 0.65 P3, 0.35 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron Vis a Vis Point with 3 edges (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 0.866, 0) { 0.5 };\n",\ +"(0.5, 0.288, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"mapedges\n",\ +"(1, 4);\n",\ +"(2, 4);\n",\ +"(3, 4);\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(4, 3, 1);\n",\ +"(4, 2, 3);\n",\ +"(4, 1, 2);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, 0.45 P2, -0.35 P3, 0.45 P4 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P2, 0.3334 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron Vis a Vis Triangle (1)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 0.866, 0) { 0.5 };\n",\ +"(0, 0, -0.816) { 0.5 };\n",\ +"(1, 0, -0.816) { 0.5 };\n",\ +"(0.5, 0.866, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(4, 6, 5) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(1, 2, 4);\n",\ +"(2, 5, 4);\n",\ +"(2, 3, 6);\n",\ +"(2, 6, 5);\n",\ +"(3, 1, 4);\n",\ +"(3, 4, 6);\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"(4, 2, 3, 6);\n",\ +"(4, 2, 6, 5);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ -0.2 P1, 0.35 P2, 0.35 P3, -0.2 P4, 0.35 P5, 0.35 P6 };\n",\ +"{ 0.35 P1, -0.2 P2, 0.35 P3, 0.35 P4, -0.2 P5, 0.35 P6 };\n",\ +"{ 0.35 P1, 0.35 P2, -0.2 P3, 0.35 P4, 0.35 P5, -0.2 P6 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Octaeder 1\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.95 };\n",\ +"(0.5, 0.866, 0) { 0.95 };\n",\ +"(0.5, -0.288, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(1, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"(0, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(2, 3, 5);\n",\ +"(3, 1, 6);\n",\ +"(3, 6, 5);\n",\ +"(2, 5, 4);\n",\ +"(1, 4, 6);\n",\ +"(4, 5, 6);\n",\ +"\n",\ +"elements\n",\ +"(3, 4, 1, 2);\n",\ +"(3, 4, 2, 5);\n",\ +"(3, 4, 5, 6);\n",\ +"(3, 4, 6, 1);\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 };\n",\ +"(-0.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 1 Z4 };\n",\ +"( 1.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 1 Z4 };\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Octaeder 2\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.95 };\n",\ +"(0.5, 0.866, 0) { 0.95 };\n",\ +"(0.5, -0.288, -0.816) { 0.5 };\n",\ +"(1, 0.578, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(2, 3, 5);\n",\ +"(3, 1, 6);\n",\ +"(3, 6, 5);\n",\ +"(2, 5, 4);\n",\ +"(1, 4, 6);\n",\ +"(4, 5, 6);\n",\ +"\n",\ +"elements\n",\ +"(3, 4, 1, 2);\n",\ +"(3, 4, 2, 5);\n",\ +"(3, 4, 5, 6);\n",\ +"(3, 4, 6, 1);\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 };\n",\ +"(1, 0.578, -0.816) { 1 X5 } { 1 Y5 } { 1 Z5 };\n",\ +"\n",\ +"(0.9, 0.097, -0.544) { 0.333 X2, 0.333 X4, 0.333 X5 }\n",\ +" { 0.333 Y2, 0.333 Y4, 0.333 Y5 }\n",\ +" { 0.333 Z2, 0.333 Z4, 0.333 Z5 };\n",\ +"(0.9, 0.481, -0.272) { 0.333 X2, 0.333 X3, 0.333 X5 }\n",\ +" { 0.333 Y2, 0.333 Y3, 0.333 Y5 }\n",\ +" { 0.333 Z2, 0.333 Z3, 0.333 Z5 };\n",\ +"\n",\ +"(-0.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 0.5 Z4, 0.5 Z5 };\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"rule \"Octaeder 2a\"\n",\ +"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.95 };\n",\ +"(0.5, 0.866, 0) { 0.95 };\n",\ +"(0.5, -0.288, -0.816) { 0.5 };\n",\ +"(1, 0.578, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(3, 2, 5) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0, 0.578, -0.816)\n",\ +" { -1 X2, 1 X3, 1 X4 }\n",\ +" { -1 Y2, 1 Y3, 1 Y4 }\n",\ +" { -1 Z2, 1 Z3, 1 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(1, 2, 4);\n",\ +"(3, 1, 6);\n",\ +"(3, 6, 5);\n",\ +"(2, 5, 4);\n",\ +"(1, 4, 6);\n",\ +"(4, 5, 6);\n",\ +"\n",\ +"elements\n",\ +"(3, 4, 1, 2);\n",\ +"(3, 4, 2, 5);\n",\ +"(3, 4, 5, 6);\n",\ +"(3, 4, 6, 1);\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 };\n",\ +"(1, 0.578, -0.816) { 1 X5 } { 1 Y5 } { 1 Z5 };\n",\ +"\n",\ +"(0.9, 0.097, -0.544) { 0.333 X2, 0.333 X4, 0.333 X5 }\n",\ +" { 0.333 Y2, 0.333 Y4, 0.333 Y5 }\n",\ +" { 0.333 Z2, 0.333 Z4, 0.333 Z5 };\n",\ +"\n",\ +"(0.5, -0.097, -0.272) { 0.333 X2, 0.333 X4, 0.333 X1 }\n",\ +" { 0.333 Y2, 0.333 Y4, 0.333 Y1 }\n",\ +" { 0.333 Z2, 0.333 Z4, 0.333 Z1 };\n",\ +"\n",\ +"(-0.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 0.5 Z4, 0.5 Z5 };\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Pyramid 1\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 };\n",\ +"(0.5, 0.866, 0) { 1 };\n",\ +"(0.5, -0.288, -0.816) { 1 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(1, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(1, 4, 3);\n",\ +"(2, 3, 5);\n",\ +"(2, 5, 4);\n",\ +"(4, 5, 3);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"(4, 2, 3, 5);\n",\ +"\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 };\n",\ +"(0, 1, -1) { 0.5 X3, 0.5 X4 } { 1 Y3 } { 1 Z4 };\n",\ +"(1.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 2 times 60\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.3 };\n",\ +"(0.5, 0.866, 0) { 0.3 };\n",\ +"(0.5, 0.288, -0.816) { 0.3 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(2, 4, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(1, 4, 3);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.4 P1, 0.4 P4, 0.4 P3, -0.2 P2 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Fill Tetrahedron (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.2 };\n",\ +"(0.5, 0.866, 0) { 0.2 };\n",\ +"(0.5, 0.288, -0.816) { 0.2 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(2, 4, 3) del;\n",\ +"(3, 4, 1) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 120 (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 };\n",\ +"(0.5, 0.866, 0) { 1 };\n",\ +"(0.5, -0.674, -0.544) { 1 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.288, -0.816)\n",\ +" { -0.5 X1, -0.5 X2, 1 X3, 1 X4 }\n",\ +" { -0.5 Y1, -0.5 Y2, 1 Y3, 1 Y4}\n",\ +" { -0.5 Z1, -0.5 Z2, 1 Z3, 1 Z4};\n",\ +"\n",\ +"newfaces\n",\ +"(1, 5, 3);\n",\ +"(3, 5, 2);\n",\ +"(1, 4, 5);\n",\ +"(2, 5, 4);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 5);\n",\ +"(1, 4, 2, 5);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1.3 P5, -0.3 P1 };\n",\ +"{ 1.3 P5, -0.3 P2 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P5 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 2 times 120 (1)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 };\n",\ +"(0.5, 0.866, 0) { 1 };\n",\ +"(0.5, -0.674, -0.544) { 0.8 };\n",\ +"(1.334, 0.77, -0.544) { 0.8 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(3, 2, 5) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.288, -0.816) { 0.25 X1, -0.5 X2, 0.25 X3, 0.5 X4, 0.5 X5 }\n",\ +" { 0.25 Y1, -0.5 Y2, 0.25 Y3, 0.5 Y4, 0.5 Y5 }\n",\ +" { 0.25 Z1, -0.5 Z2, 0.25 Z3, 0.5 Z4, 0.5 Z5 };\n",\ +"\n",\ +"newfaces\n",\ +"(6, 3, 1);\n",\ +"(6, 1, 4);\n",\ +"(6, 4, 2);\n",\ +"(6, 2, 5);\n",\ +"(6, 5, 3);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 6);\n",\ +"(1, 4, 2, 6);\n",\ +"(2, 5, 3, 6);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1.4 P6, -0.4 P2 };\n",\ +"{ 1.4 P6, -0.4 P1 };\n",\ +"{ 1.4 P6, -0.4 P3 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"four Tetrahedron non convex (4)\"\n",\ +"\n",\ +"quality 4\n",\ +"flags l;\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.1 };\n",\ +"(0.5, 1, 0) { 0.1 };\n",\ +"(0.5, 0, -1) { 0.1 };\n",\ +"(0.5, 0.3, -0.3) { 0.1 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(1, 5, 4) del;\n",\ +"(1, 3, 5) del;\n",\ +"\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.1, -0.1)\n",\ +" { 0.333 X1, 0.333 X2, 0.334 X5 }\n",\ +" { 0.333 Y1, 0.333 Y2, 0.334 Y5 }\n",\ +" { 0.333 Z1, 0.333 Z2, 0.334 Z5 };\n",\ +"\n",\ +"newfaces\n",\ +"(6, 2, 3) del;\n",\ +"(6, 4, 2) del;\n",\ +"(6, 5, 4) del;\n",\ +"(6, 3, 5) del;\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 6);\n",\ +"(1, 4, 2, 6);\n",\ +"(1, 5, 4, 6);\n",\ +"(1, 3, 5, 6);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1.5 P6, -0.5 P1 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"\n",\ +"\n",\ +"\n",\ +"freeset\n",\ +"1 6 2 3;\n",\ +"\n",\ +"freeset\n",\ +"1 6 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 6 5 4;\n",\ +"\n",\ +"freeset\n",\ +"1 6 4 2;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"five Tetrahedron non convex (4)\"\n",\ +"\n",\ +"quality 4\n",\ +"flags l;\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0, 0.8, -0.2) { 0.5 };\n",\ +"(0, 0.2, -0.8) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 3, 4) del;\n",\ +"(1, 4, 5) del;\n",\ +"(1, 5, 6) del;\n",\ +"(1, 6, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.1, 0.1, -0.1)\n",\ +" { 0.75 X1, 0.05 X2, 0.05 X3, 0.05 X4, 0.05 X5, 0.05 X6 }\n",\ +" { 0.75 Y1, 0.05 Y2, 0.05 Y3, 0.05 Y4, 0.05 Y5, 0.05 Y6 }\n",\ +" { 0.75 Z1, 0.05 Z2, 0.05 Z3, 0.05 Z4, 0.05 Z5, 0.05 Z6 };\n",\ +"\n",\ +"newfaces\n",\ +"(7, 2, 3);\n",\ +"(7, 3, 4);\n",\ +"(7, 4, 5);\n",\ +"(7, 5, 6);\n",\ +"(7, 6, 2);\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 7);\n",\ +"(1, 3, 4, 7);\n",\ +"(1, 4, 5, 7);\n",\ +"(1, 5, 6, 7);\n",\ +"(1, 6, 2, 7);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ 1.5 P7, -0.5 P1 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ 1 P7 };\n",\ +"\n",\ +"\n",\ +"\n",\ +"freeset\n",\ +"1 7 2 3;\n",\ +"\n",\ +"freeset\n",\ +"1 7 3 4;\n",\ +"\n",\ +"freeset\n",\ +"1 7 4 5;\n",\ +"\n",\ +"freeset\n",\ +"1 7 5 6;\n",\ +"\n",\ +"freeset\n",\ +"1 7 6 2;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"four Tetrahedron non convex (6)\"\n",\ +"\n",\ +"quality 6\n",\ +"flags l;\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"(0.5, 0.3, -0.3) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(1, 5, 4) del;\n",\ +"(1, 3, 5) del;\n",\ +"\n",\ +"\n",\ +"newpoints\n",\ +"(0.095, 0.003, -0.003)\n",\ +" { 0.9 X1, 0.09 X2, 0.01 X5 }\n",\ +" { 0.9 Y1, 0.09 Y2, 0.01 Y5 }\n",\ +" { 0.9 Z1, 0.09 Z2, 0.01 Z5 };\n",\ +"\n",\ +"newfaces\n",\ +"(6, 2, 3) del;\n",\ +"(6, 4, 2) del;\n",\ +"(6, 5, 4) del;\n",\ +"(6, 3, 5) del;\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 6);\n",\ +"(1, 4, 2, 6);\n",\ +"(1, 5, 4, 6);\n",\ +"(1, 3, 5, 6);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1.499 P6, -0.5 P1, 0.001 P2 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"\n",\ +"\n",\ +"\n",\ +"freeset\n",\ +"1 6 2 3;\n",\ +"\n",\ +"freeset\n",\ +"1 6 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 6 5 4;\n",\ +"\n",\ +"freeset\n",\ +"1 6 4 2;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"four Tetrahedron non convex (6)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"(0.5, 0.4, -0.4) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(4, 5, 2) del;\n",\ +"(5, 3, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.925, 0.02, -0.02)\n",\ +" { 0.05 X1, 0.9 X2, 0.05 X5 }\n",\ +" { 0.05 Y1, 0.9 Y2, 0.05 Y5 }\n",\ +" { 0.05 Z1, 0.9 Z2, 0.05 Z5 };\n",\ +"\n",\ +"newfaces\n",\ +"(3, 1, 6);\n",\ +"(1, 4, 6);\n",\ +"(4, 5, 6);\n",\ +"(5, 3, 6);\n",\ +"\n",\ +"elements\n",\ +"(3, 1, 2, 6);\n",\ +"(1, 4, 2, 6);\n",\ +"(4, 5, 2, 6);\n",\ +"(5, 3, 2, 6);\n",\ +"\n",\ +"orientations\n",\ +"(3, 1, 2, 5);\n",\ +"(1, 4, 2, 5);\n",\ +"(2, 4, 5, 1);\n",\ +"(3, 2, 5, 1);\n",\ +"(5, 4, 2, 3);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1.5 P6, -0.5 P2 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"\n",\ +"freeset\n",\ +"3 1 2 6;\n",\ +"\n",\ +"freeset\n",\ +"1 4 2 6;\n",\ +"\n",\ +"freeset\n",\ +"4 5 2 6;\n",\ +"\n",\ +"freeset\n",\ +"5 3 2 6;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"three Tetrahedron non convex (4)\"\n",\ +"\n",\ +"quality 4\n",\ +"flags l;\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(1, 3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.25, -0.25)\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",\ +" { 0.25 Z1, 0.25 Z2, 0.25 Z3, 0.25 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(5, 2, 3);\n",\ +"(5, 4, 2);\n",\ +"(5, 3, 4);\n",\ +"\n",\ +"elements\n",\ +"(2, 3, 1, 5);\n",\ +"(3, 4, 1, 5);\n",\ +"(4, 2, 1, 5;\n",\ +"\n",\ +"orientations\n",\ +"(1, 2, 4, 3);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1.5 P5, -0.5 P1 };\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",\ +"freeset\n",\ +"1 4 2 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"three Tetrahedron non convex (6)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(1, 3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.2, 0.1, -0.1)\n",\ +" { 0.7 X1, 0.1 X2, 0.1 X3, 0.1 X4 }\n",\ +" { 0.7 Y1, 0.1 Y2, 0.1 Y3, 0.1 Y4 }\n",\ +" { 0.7 Z1, 0.1 Z2, 0.1 Z3, 0.1 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(5, 2, 3);\n",\ +"(5, 4, 2);\n",\ +"(5, 3, 4);\n",\ +"\n",\ +"elements\n",\ +"(2, 3, 1, 5);\n",\ +"(3, 4, 1, 5);\n",\ +"(4, 2, 1, 5;\n",\ +"\n",\ +"orientations\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1.5 P5, -0.5 P1 };\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",\ +"freeset\n",\ +"1 4 2 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"four Tetrahedron non convex (6)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"(0.5, 0.4, -0.4) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(4, 5, 2) del;\n",\ +"(5, 3, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.7, 0.08, -0.08) { 0.6 X2, 0.2 X5 } { 0.2 Y5 } { 0.2 Z5 };\n",\ +"\n",\ +"newfaces\n",\ +"(3, 1, 6);\n",\ +"(1, 4, 6);\n",\ +"(4, 5, 6);\n",\ +"(5, 3, 6);\n",\ +"\n",\ +"elements\n",\ +"(3, 1, 2, 6);\n",\ +"(1, 4, 2, 6);\n",\ +"(4, 5, 2, 6);\n",\ +"(5, 3, 2, 6);\n",\ +"\n",\ +"\n",\ +"orientations\n",\ +"(3, 1, 2, 5);\n",\ +"(5, 1, 2, 4);\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 1, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, 0, -1) { 1 X4 } { 1 Y4 } { 1 Z4 };\n",\ +"(0.5, 0.4, -0.4) { 1 X5 } { 1 Y5 } { 1 Z5 };\n",\ +"(0.55, 0.12, -0.12) { 0.4 X2, 0.3 X5 } { 0.3 Y5 } { 0.3 Z5 };\n",\ +"\n",\ +"freeset\n",\ +"3 1 2 6;\n",\ +"\n",\ +"freeset\n",\ +"1 4 2 6;\n",\ +"\n",\ +"freeset\n",\ +"4 5 2 6;\n",\ +"\n",\ +"freeset\n",\ +"5 3 2 6;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 2 in 60 (12)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.1, -0.1)\n",\ +" { 0.4 X1, 0.4 X2, 0.1 X3, 0.1 X4 }\n",\ +" { 0.4 Y1, 0.4 Y2, 0.1 Y3, 0.1 Y4 }\n",\ +" { 0.4 Z1, 0.4 Z2, 0.1 Z3, 0.1 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(5, 2, 3);\n",\ +"(5, 3, 1);\n",\ +"(5, 4, 2);\n",\ +"(5, 1, 4);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 5);\n",\ +"(1, 2, 5, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1.5 P5, -0.25 P1, -0.25 P2 };\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 2 4 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 120, but more than 180 (13)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 };\n",\ +"(0.5, 0.866, 0) { 1 };\n",\ +"(0.5, -0.866, 0) { 1 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2);\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0, -0.3) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(1, 5, 3);\n",\ +"(3, 5, 2);\n",\ +"(2, 5, 1);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 5);\n",\ +"\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, -0.1, -0.4) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Free Tetrahedron (14)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1.0 };\n",\ +"(0.5, 0.866, 0) { 1.0 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.288, -0.2) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { };\n",\ +"\n",\ +"newfaces\n",\ +"(4, 1, 2);\n",\ +"(4, 2, 3);\n",\ +"(4, 3, 1);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, 0.288, -0.25) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { };\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Free Tetrahedron (15)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1.0 };\n",\ +"(0.5, 0.866, 0) { 1.0 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.288, -0.1) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { };\n",\ +"\n",\ +"newfaces\n",\ +"(4, 1, 2);\n",\ +"(4, 2, 3);\n",\ +"(4, 3, 1);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, 0.288, -0.15) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { };\n",\ +"\n",\ +"endrule\n", +0}; +} diff --git a/contrib/Netgen/libsrc/meshing/topology.cpp b/contrib/Netgen/libsrc/meshing/topology.cpp new file mode 100644 index 0000000000..e620854cbf --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/topology.cpp @@ -0,0 +1,1726 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + template <class T> + void QuickSortRec (FlatArray<T> & 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 <class T> + void QuickSort (FlatArray<T> & data) + { + if (data.Size() > 1) + QuickSortRec (data, 0, data.Size()-1); + } + + + + + + + MeshTopology :: MeshTopology (const Mesh & amesh) + : mesh(amesh) + { + buildedges = 1; + buildfaces = 1; + vert2element = 0; + vert2surfelement = 0; + vert2segment = 0; + timestamp = -1; + + edge2vert.SetName ("edge2vert"); + face2vert.SetName ("face2vert"); + edges.SetName ("el2edge"); + faces.SetName ("el2face"); + surfedges.SetName ("surfel2edge"); + segedges.SetName ("segment2edge"); + surffaces.SetName ("surfel2face"); + surf2volelement.SetName ("surfel2el"); + face2surfel.SetName ("face2surfel"); + } + + MeshTopology :: ~MeshTopology () + { + delete vert2element; + delete vert2surfelement; + delete vert2segment; + } + + void MeshTopology :: Update() + { + static int timer = NgProfiler::CreateTimer ("topology"); + NgProfiler::RegionTimer reg (timer); + +#ifdef PARALLEL + ParallelMeshTopology & paralleltop = mesh.GetParallelTopology(); +#endif + + bool isparallel = 0; + + + 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(); + int nfa = 0; + int ned = edge2vert.Size(); + + 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; + + delete vert2element; + delete vert2surfelement; + delete vert2segment; + + Array<int,PointIndex::BASE> cnt(nv); + Array<int> 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]]++; + } + + vert2element = new TABLE<int,PointIndex::BASE> (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+1); + } + + 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]]++; + } + + vert2surfelement = new TABLE<int,PointIndex::BASE> (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+1); + } + + cnt = 0; + for (int i = 1; i <= nseg; i++) + { + const Segment & seg = mesh.LineSegment(i); + cnt[seg[0]]++; + cnt[seg[1]]++; + } + + vert2segment = new TABLE<int,PointIndex::BASE> (cnt); + for (int i = 1; i <= nseg; i++) + { + const Segment & seg = mesh.LineSegment(i); + vert2segment->AddSave (seg[0], i); + vert2segment->AddSave (seg[1], i); + } + + + 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] = 0; + for (int i = 0; i < nse; i++) + for (int j = 0; j < 4; j++) + surfedges[i][j] = 0; + + // keep existing edges + cnt = 0; + for (int i = 0; i < edge2vert.Size(); i++) + cnt[edge2vert[i][0]]++; + TABLE<int,PointIndex::BASE> vert2edge (cnt); + for (int i = 0; i < edge2vert.Size(); i++) + vert2edge.AddSave (edge2vert[i][0], i+1); + + // ensure all coarse grid and intermediate level edges + cnt = 0; + for (int i = mesh.mlbetweennodes.Begin(); i < mesh.mlbetweennodes.End(); i++) + { + /* JS, Oct 2009 + int pa[2]; + pa[0] = mesh.mlbetweennodes[i].I1(); + pa[1] = mesh.mlbetweennodes[i].I2(); + if (pa[0] > pa[1]) Swap (pa[0], pa[1]); + if (pa[0] > 0) + cnt.Elem(pa[0])++; + */ + INDEX_2 parents = mesh.mlbetweennodes[i]; + parents.Sort(); + if (parents[0] >= PointIndex::BASE) cnt[parents[0]]++; + } + + TABLE<int,PointIndex::BASE> vert2vertcoarse (cnt); + for (int i = mesh.mlbetweennodes.Begin(); i < mesh.mlbetweennodes.End(); i++) + { + /* + int pa[2]; + pa[0] = mesh.mlbetweennodes[i].I1(); + pa[1] = mesh.mlbetweennodes[i].I2(); + if (pa[0] > pa[1]) swap (pa[0], pa[1]); + if (pa[0] > 0) + vert2vertcoarse.AddSave1 (pa[0], pa[1]); + */ + INDEX_2 parents = mesh.mlbetweennodes[i]; + parents.Sort(); + if (parents[0] > PointIndex::BASE) vert2vertcoarse.AddSave (parents[0], parents[1]); + } + + + Array<int,PointIndex::BASE> edgenr(nv); + Array<int,PointIndex::BASE> edgeflag(nv); + Array<int> vertex2; + + edgeflag = 0; + + ned = edge2vert.Size(); + Array<INDEX_3> missing; + + for (int i = PointIndex::BASE; i < nv+PointIndex::BASE; i++) + { + vertex2.SetSize (0); + + for (int j = 0; j < vert2edge[i].Size(); j++) + { + int ednr = vert2edge[i][j]; + int i2 = edge2vert.Get(ednr)[1]; + edgeflag[i2] = i; + edgenr[i2] = ednr; + } + + for (int j = 0; j < vert2vertcoarse[i].Size(); j++) // fix by Markus + { + int v2 = vert2vertcoarse[i][j]; + if (edgeflag[v2] < i) + { + *testout << "do we really need that ??????????????" << endl; + // ned++; + // edgenr[v2] = ned; + edgeflag[v2] = i; + vertex2.Append (v2); + // missing.Append (INDEX_3(i,v2,ned)); + } + } + + for (int j = 0; j < (*vert2element)[i].Size(); j++) + { + int elnr = (*vert2element)[i][j]; + const Element & el = mesh.VolumeElement (elnr); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges0 (el.GetType()); + + for (int k = 0; k < neledges; k++) + { + INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]); + edge.Sort(); + if (edge.I1() != i) continue; + + if (edgeflag[edge.I2()] < i) + { + vertex2.Append (edge.I2()); + edgeflag[edge.I2()] = i; + } + } + } + + for (int j = 0; j < (*vert2surfelement)[i].Size(); j++) + { + int elnr = (*vert2surfelement)[i][j]; + const Element2d & el = mesh.SurfaceElement (elnr); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges0 (el.GetType()); + + for (int k = 0; k < neledges; k++) + { + INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]); + edge.Sort(); + if (edge.I1() != i) continue; + + if (edgeflag[edge.I2()] < i) + { + vertex2.Append (edge.I2()); + edgeflag[edge.I2()] = i; + } + } + } + + for (int j = 0; j < (*vert2segment)[i].Size(); j++) + { + int elnr = (*vert2segment)[i][j]; + const Segment & el = mesh.LineSegment (elnr); + + INDEX_2 edge(el[0], el[1]); + edge.Sort(); + if (edge.I1() != i) continue; + + if (edgeflag[edge.I2()] < i) + { + vertex2.Append (edge.I2()); + edgeflag[edge.I2()] = i; + } + } + + + QuickSort (vertex2); + for (int j = 0; j < vertex2.Size(); j++) + edgenr[vertex2[j]] = ++ned; + + for (int j = 0; j < vert2vertcoarse[i].Size(); j++) // fix by Markus + { + int v2 = vert2vertcoarse[i][j]; + if (edgeflag[v2] < i) + { + // ned++; + // edgenr[v2] = ned; + // edgeflag[v2] = i; + missing.Append (INDEX_3(i,v2,edgenr[v2])); + } + } + + for (int j = 0; j < (*vert2element)[i].Size(); j++) + { + int elnr = (*vert2element)[i][j]; + const Element & el = mesh.VolumeElement (elnr); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges0 (el.GetType()); + + for (int k = 0; k < neledges; k++) + { + INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]); + + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) swap (edge.I1(), edge.I2()); + + if (edge.I1() != i) + continue; + + int edgenum = edgenr[edge.I2()]; + if (edgedir) edgenum *= -1; + edges.Elem(elnr)[k] = edgenum; + } + } + + for (int j = 0; j < (*vert2surfelement)[i].Size(); j++) + { + int elnr = (*vert2surfelement)[i][j]; + const Element2d & el = mesh.SurfaceElement (elnr); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges0 (el.GetType()); + + for (int k = 0; k < neledges; k++) + { + INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]); + + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) swap (edge.I1(), edge.I2()); + + if (edge.I1() != i) continue; + + int edgenum = edgenr[edge.I2()]; + if (edgedir) edgenum *= -1; + surfedges.Elem(elnr)[k] = edgenum; + } + } + + for (int j = 0; j < (*vert2segment)[i].Size(); j++) + { + int elnr = (*vert2segment)[i][j]; + const Segment & el = mesh.LineSegment (elnr); + + INDEX_2 edge(el[0], el[1]); + + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) swap (edge.I1(), edge.I2()); + + if (edge.I1() != i) continue; + + int edgenum = edgenr[edge.I2()]; + if (edgedir) edgenum *= -1; + segedges.Elem(elnr) = edgenum; + } + } + + + + edge2vert.SetSize (ned); + for (int i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement (i); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges0 (el.GetType()); + + for (int k = 0; k < neledges; k++) + { + INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]); + + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) swap (edge.I1(), edge.I2()); + + int edgenum = abs (edges.Elem(i)[k]); + + edge2vert.Elem(edgenum)[0] = edge.I1(); + edge2vert.Elem(edgenum)[1] = edge.I2(); + } + } + + /* + *testout << "edge 2 vert:" << endl; + for (int i = 0; i < edge2vert.Size(); i++) + *testout << edge2vert[i][0] << " " << edge2vert[i][1] << endl; + */ + + for (int i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement (i); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges0 (el.GetType()); + + for (int k = 0; k < neledges; k++) + { + INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]); + + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) swap (edge.I1(), edge.I2()); + + int edgenum = abs (surfedges.Elem(i)[k]); + + edge2vert.Elem(edgenum)[0] = edge.I1(); + edge2vert.Elem(edgenum)[1] = edge.I2(); + } + } + + for (int i = 1; i <= nseg; i++) + { + const Segment & el = mesh.LineSegment (i); + + INDEX_2 edge(el[0], el[1]); + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) swap (edge.I1(), edge.I2()); + + int edgenum = abs (segedges.Elem(i)); + + edge2vert.Elem(edgenum)[0] = edge.I1(); + edge2vert.Elem(edgenum)[1] = edge.I2(); + } + + for (int i = 1; i <= missing.Size(); i++) + { + INDEX_3 i3 = missing.Get(i); + edge2vert.Elem(i3.I3())[0] = i3.I1(); + edge2vert.Elem(i3.I3())[1] = i3.I2(); + } + + + /* + (*testout) << "edge table:" << endl; + (*testout) << "edge2vert:" << endl; + for (int i = 1; i <= edge2vert.Size(); i++) + (*testout) << "edge " << i << ", v1,2 = " << edge2vert.Elem(i)[0] << ", " << edge2vert.Elem(i)[1] << endl; + (*testout) << "surfedges:" << endl; + for (int i = 1; i <= surfedges.Size(); i++) + (*testout) << "el " << i << ", edges = " + << surfedges.Elem(i)[0] << ", " + << surfedges.Elem(i)[1] << ", " + << surfedges.Elem(i)[2] << endl; + */ + + + } + + + // cout << "build edges done" << endl; + + + + // generate faces + if (buildfaces) // && mesh.GetDimension() == 3) + { + static int timer2 = NgProfiler::CreateTimer ("topology::buildfaces"); + NgProfiler::RegionTimer reg2 (timer2); + + if (id == 0) + PrintMessage (5, "Update faces "); + + + + + faces.SetSize(ne); + surffaces.SetSize(nse); + + int oldnfa = face2vert.Size(); + + cnt = 0; + for (int i = 0; i < face2vert.Size(); i++) + cnt[face2vert[i][0]]++; + TABLE<int,PointIndex::BASE> 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] = 0; + + + 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); + } + + + /* + for (int pass = 1; pass <= 2; pass++) + { + nfa = oldnfa; + for (int v = PointIndex::BASE; v < nv+PointIndex::BASE; v++) + { + INDEX_3_CLOSED_HASHTABLE<int> vert2face(2*max_face_on_vertex+10); + + 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); + } + + + // cout << "inherited faces: " << endl << vert2face << endl; + + + for (int j = 0; j < (*vert2element)[v].Size(); j++) + { + int elnr = (*vert2element)[v][j]; + const Element & el = mesh.VolumeElement (elnr); + + int nelfaces = GetNFaces (el.GetType()); + const ELEMENT_FACE * elfaces = GetFaces1 (el.GetType()); + + for (int j = 0; j < nelfaces; j++) + if (elfaces[j][3] == 0) + + { // triangle + int facenum, facedir; + INDEX_3 face(el.PNum(elfaces[j][0]), + el.PNum(elfaces[j][1]), + el.PNum(elfaces[j][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); + if (pass == 2) face2vert.Append (hface); + } + faces.Elem(elnr)[j] = 8*(facenum-1)+facedir+1; + } + + else + + { + // quad + int facenum, facedir; + INDEX_4Q face4(el.PNum(elfaces[j][0]), + el.PNum(elfaces[j][1]), + el.PNum(elfaces[j][2]), + el.PNum(elfaces[j][3])); + + 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 + { + nfa++; + vert2face.Set (face, nfa); + facenum = nfa; + + INDEX_4 hface(face4.I1(),face4.I2(),face4.I3(),face4.I4()); + if (pass == 2) face2vert.Append (hface); + } + + faces.Elem(elnr)[j] = 8*(facenum-1)+facedir+1; + } + } + + for (int j = 0; j < (*vert2surfelement)[v].Size(); j++) + { + int elnr = (*vert2surfelement)[v][j]; + // cout << "surfelnr = " << elnr << endl; + 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])); + + // cout << "face = " << face << endl; + + 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); + if (pass == 2) face2vert.Append (hface); + } + + // cout << "face = " << face << " selnr = " << elnr << endl; + surffaces.Elem(elnr) = 8*(facenum-1)+facedir+1; + // face2surfel.Elem(facenum) = elnr; + } + + 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.I3()); + if (pass == 2) face2vert.Append (hface); + } + + surffaces.Elem(elnr) = 8*(facenum-1)+facedir+1; + } + } + } + + face2vert.SetAllocSize (nfa); + } + */ + + + + + + + + + for (int pass = 1; pass <= 2; pass++) + { + nfa = oldnfa; + for (int v = PointIndex::BASE; v < nv+PointIndex::BASE; v++) + { + int first_fa = nfa; + + INDEX_3_CLOSED_HASHTABLE<int> vert2face(2*max_face_on_vertex+10); + + 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); + } + + + if (pass == 2) + for (int j = nfa; 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); + nfa++; + } + else + break; + } + + + // cout << "inherited faces: " << endl << vert2face << endl; + + + for (int j = 0; j < (*vert2element)[v].Size(); j++) + { + int elnr = (*vert2element)[v][j]; + const Element & el = mesh.VolumeElement (elnr); + + int nelfaces = GetNFaces (el.GetType()); + const ELEMENT_FACE * elfaces = GetFaces1 (el.GetType()); + + for (int j = 0; j < nelfaces; j++) + if (elfaces[j][3] == 0) + + { // triangle + int facenum, facedir; + INDEX_3 face(el.PNum(elfaces[j][0]), + el.PNum(elfaces[j][1]), + el.PNum(elfaces[j][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); + } + faces.Elem(elnr)[j] = 8*(facenum-1)+facedir+1; + } + + else + + { + // quad + int facenum, facedir; + INDEX_4Q face4(el.PNum(elfaces[j][0]), + el.PNum(elfaces[j][1]), + el.PNum(elfaces[j][2]), + el.PNum(elfaces[j][3])); + + 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 + { + nfa++; + vert2face.Set (face, nfa); + facenum = nfa; + + INDEX_4 hface(face4.I1(),face4.I2(),face4.I3(),face4.I4()); + face2vert.Append (hface); + } + + faces.Elem(elnr)[j] = 8*(facenum-1)+facedir+1; + } + } + + for (int j = 0; j < (*vert2surfelement)[v].Size(); j++) + { + int elnr = (*vert2surfelement)[v][j]; + // cout << "surfelnr = " << elnr << endl; + 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])); + + // cout << "face = " << face << endl; + + 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.Elem(elnr) = 8*(facenum-1)+facedir+1; + } + + 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.I3()); + face2vert.Append (hface); + } + + surffaces.Elem(elnr) = 8*(facenum-1)+facedir+1; + } + } + + // sort faces + // *testout << "faces = " << face2vert << endl; + if (pass == 1) + { + // *testout << "sort from " << first_fa << " to " << nfa << endl; + for (int i = first_fa; i < nfa; i++) + for (int j = first_fa+1; j < nfa; j++) + if (face2vert[j] < face2vert[j-1]) + Swap (face2vert[j-1], face2vert[j]); + } + // *testout << "faces, sorted = " << face2vert << endl; + } + + + face2vert.SetAllocSize (nfa); + + } + + + // *testout << "face2vert = " << endl << face2vert << endl; + + + + + + + + + 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; + } + for (int i = 1; i <= ne; i++) + for (int j = 0; j < 6; j++) + { + int fnum = (faces.Get(i)[j]+7) / 8; + if (fnum > 0 && face2surfel.Elem(fnum)) + { + int sel = face2surfel.Elem(fnum); + surf2volelement.Elem(sel)[1] = + surf2volelement.Elem(sel)[0]; + surf2volelement.Elem(sel)[0] = i; + } + } + + face2vert.SetAllocSize (face2vert.Size()); + + // face table complete + + +#ifdef PARALLEL + (*testout) << " RESET Paralleltop" << endl; + paralleltop.Reset (); +#endif + + Array<short int> face_els(nfa), face_surfels(nfa); + face_els = 0; + face_surfels = 0; + Array<int> hfaces; + for (int i = 1; i <= ne; i++) + { + GetElementFaces (i, hfaces); + for (int j = 0; j < hfaces.Size(); j++) + face_els[hfaces[j]-1]++; + } + for (int i = 1; i <= nse; i++) + face_surfels[GetSurfaceElementFace (i)-1]++; + + + 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 ) + { + 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<int> vertels = GetVertexElements (face2vert[i].I(1)); + for (int k = 0; k < vertels.Size(); k++) + { + int elfaces[10], orient[10]; + int nf = GetElementFaces (vertels[k], 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.VolumeElement (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; + + if (cnt_err && ntasks > 1) + isparallel = 1; + } + } + + +#ifdef PARALLEL + if (mesh.GetDimension() == 3) + if (isparallel != (id != 0)) + { + cerr << " ****************************** " << endl; + cerr << " **** wrong isparallel ****** " << endl; + cerr << " ****************************** " << endl; + } + + if (id != 0) // if (isparallel) + { + paralleltop.Update(); + 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<int> & eledges) const + { + int ned = GetNEdges (mesh.VolumeElement(elnr).GetType()); + eledges.SetSize (ned); + for (int i = 0; i < ned; i++) + eledges[i] = abs (edges.Get(elnr)[i]); + } + void MeshTopology :: GetElementFaces (int elnr, Array<int> & 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; + } + + else + + 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<int> & 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; + } + + void MeshTopology :: GetElementFaceOrientations (int elnr, Array<int> & 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]-1) % 8; + } + + + + 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; + } + } + else + { + for (int i = 0; i < 12; i++) + { + if (!edges.Get(elnr)[i]) return i; + eledges[i] = abs (edges.Get(elnr)[i]); + } + } + 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; + } + } + else + { + for (int i = 0; i < 6; i++) + { + if (!faces.Get(elnr)[i]) return i; + elfaces[i] = (faces.Get(elnr)[i]-1) / 8 + 1; + } + } + return 6; + } + + void MeshTopology :: GetSurfaceElementEdges (int elnr, Array<int> & eledges) const + { + int i; + if (mesh.GetDimension()==3 || 1) + { + int ned = GetNEdges (mesh.SurfaceElement(elnr).GetType()); + eledges.SetSize (ned); + for (i = 1; i <= ned; i++) + eledges.Elem(i) = abs (surfedges.Get(elnr)[i-1]); + } + else + { + cout << "surfeledge(" << elnr << ") = " << flush; + eledges.SetSize(1); + eledges.Elem(1) = abs (segedges.Get(elnr)); + cout << eledges.Elem(1) << endl; + } + } + + int MeshTopology :: GetSurfaceElementFace (int elnr) const + { + return (surffaces.Get(elnr)-1) / 8 + 1; + } + + void MeshTopology :: + GetSurfaceElementEdgeOrientations (int elnr, Array<int> & eorient) const + { + int ned = GetNEdges (mesh.SurfaceElement(elnr).GetType()); + eorient.SetSize (ned); + for (int i = 1; i <= ned; i++) + eorient.Elem(i) = (surfedges.Get(elnr)[i-1] > 0) ? 1 : -1; + } + + int MeshTopology :: GetSurfaceElementFaceOrientation (int elnr) const + { + return (surffaces.Get(elnr)-1) % 8; + } + + 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; + } + } + else + { + for (i = 0; i < 4; i++) + { + if (!surfedges.Get(elnr)[i]) return i; + eledges[i] = abs (surfedges.Get(elnr)[i]); + } + } + return 4; + } + else + { + eledges[0] = abs (segedges.Get(elnr)); + if (orient) + orient[0] = segedges.Get(elnr) > 0 ? 1 : -1; + } + return 1; + } + + + void MeshTopology :: GetFaceVertices (int fnr, Array<int> & vertices) const + { + vertices.SetSize(4); + int i; + for (i = 1; i <= 4; i++) + vertices.Elem(i) = face2vert.Get(fnr)[i-1]; + if (vertices.Elem(4) == 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 + { + v1 = edge2vert.Get(ednr)[0]; + v2 = edge2vert.Get(ednr)[1]; + } + + + void MeshTopology :: GetFaceEdges (int fnr, Array<int> & fedges, bool withorientation) const + { + ArrayMem<int,4> pi(4); + ArrayMem<int,12> 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<int,4> fp; + fp[0] = pi[0]; + for(int k=1;k<pi.Size();k++) + if(fp[k]>fp[0]) swap(fp[k],fp[0]); + + fp[1] = fp[0]+ */ + + + // GetVertexElements (pi[0], els); + FlatArray<int> 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.VolumeElement(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;m<nref_faces;m++) + { + cntv=0; + for(int j=0;j<nfa_ref_edges && ref_faces[m][j]>0;j++) + for(int k=0;k<pi.Size();k++) + { + if(el[ref_faces[m][j]-1] == pi[k]) + cntv++; + } + if (cntv == pi.Size()) + { + fa=m; + break; + } + } + + if(fa>=0) + { + const ELEMENT_EDGE * fa_ref_edges = GetEdges1 (GetFaceType(fnr)); + fedges.SetSize(nfa_ref_edges); + GetElementEdges (els[i], 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<nfa_ref_edges;k++) + { + int w1 = el[ref_faces[fa][fa_ref_edges[k][0]-1]-1]; + int w2 = el[ref_faces[fa][fa_ref_edges[k][1]-1]-1]; + + if(withorientation) + { + if(w1==vi1 && w2==vi2) + fedges[k] = eledges[j]; + if(w1==vi2 && w2==vi1) + fedges[k] = -eledges[j]; + } + else + if((w1==vi1 && w2==vi2) || (w1==vi2 && w2==vi1)) + fedges[k] = eledges[j]; + } + } + } + + // *testout << " Face " << fnr << endl; + // *testout << " GetFaceEdges " << fedges << endl; + + return; + } + } + } + + + ELEMENT_TYPE MeshTopology :: GetFaceType (int fnr) const + { + if (face2vert.Get(fnr)[3] == 0) return TRIG; else return QUAD; + } + + + void MeshTopology :: GetVertexElements (int vnr, Array<int> & elements) const + { + if (vert2element) + { + int i; + int ne = vert2element->EntrySize(vnr); + elements.SetSize(ne); + for (i = 1; i <= ne; i++) + elements.Elem(i) = vert2element->Get(vnr, i); + } + } + + + FlatArray<int> MeshTopology :: GetVertexElements (int vnr) const + { + if (vert2element) + return (*vert2element)[vnr]; + return FlatArray<int> (0,0); + } + + FlatArray<int> MeshTopology :: GetVertexSurfaceElements (int vnr) const + { + if (vert2surfelement) + return (*vert2surfelement)[vnr]; + return FlatArray<int> (0,0); + } + + + void MeshTopology :: GetVertexSurfaceElements( int vnr, + Array<int>& elements ) const + { + if (vert2surfelement) + { + 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<int> elements_v1, elementedges; + GetVertexElements ( v1, elements_v1); + int edv1, edv2; + + for ( int i = 0; i < elements_v1.Size(); i++ ) + { + GetElementEdges( elements_v1[i], 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<int> & volels ) const + { + int v1, v2; + GetEdgeVertices ( GetSegmentEdge (segnr), v1, v2 ); + Array<int> 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<int> & els) const + { + int v1, v2; + GetEdgeVertices ( GetSegmentEdge (segnr), v1, v2 ); + Array<int> 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) ); + } + + + + +} diff --git a/contrib/Netgen/libsrc/meshing/topology.hpp b/contrib/Netgen/libsrc/meshing/topology.hpp new file mode 100644 index 0000000000..a453fa84dd --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/topology.hpp @@ -0,0 +1,683 @@ +#ifndef TOPOLOGY +#define TOPOLOGY + +/**************************************************************************/ +/* File: topology.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 27. Apr. 01 */ +/**************************************************************************/ + +/* + Mesh topology + (Elements, Faces, Edges, Vertices +*/ + + +class MeshTopology +{ + const Mesh & mesh; + bool buildedges; + bool buildfaces; + + MoveableArray<INDEX_2> edge2vert; + MoveableArray<INDEX_4> face2vert; + MoveableArray<int[12]> edges; + MoveableArray<int[6]> faces; + MoveableArray<int[4]> surfedges; + MoveableArray<int> segedges; + MoveableArray<int> surffaces; + MoveableArray<INDEX_2> surf2volelement; + MoveableArray<int> face2surfel; + TABLE<int,PointIndex::BASE> *vert2element; + TABLE<int,PointIndex::BASE> *vert2surfelement; + TABLE<int,PointIndex::BASE> *vert2segment; + int timestamp; +public: + int GetNSurfedges() const {return surfedges.Size();} + + MeshTopology (const Mesh & amesh); + ~MeshTopology (); + + void SetBuildEdges (bool be) + { buildedges = be; } + void SetBuildFaces (bool bf) + { buildfaces = bf; } + + bool HasEdges () const + { return buildedges; } + bool HasFaces () const + { return buildfaces; } + + void Update(); + + + int GetNEdges () const { return edge2vert.Size(); } + int GetNFaces () const { return face2vert.Size(); } + + static inline int GetNVertices (ELEMENT_TYPE et); + static inline int GetNPoints (ELEMENT_TYPE et); + static inline int GetNEdges (ELEMENT_TYPE et); + static inline 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 abs(segedges[segnr-1]); } + int GetSegmentEdgeOrientation (int segnr) const { return sgn(segedges[segnr-1]); } + + void GetSegmentEdge (int segnr, int & enr, int & orient) const + { + enr = abs(segedges.Get(segnr)); + orient = segedges.Get(segnr) > 0 ? 1 : -1; + } + + void GetElementEdges (int elnr, Array<int> & edges) const; + void GetElementFaces (int elnr, Array<int> & faces, bool withorientation = false) const; + void GetElementEdgeOrientations (int elnr, Array<int> & eorient) const; + void GetElementFaceOrientations (int elnr, Array<int> & forient) const; + + int GetElementEdges (int elnr, int * edges, int * orient) const; + int GetElementFaces (int elnr, int * faces, int * orient) const; + + void GetFaceVertices (int fnr, Array<int> & vertices) const; + void GetFaceVertices (int fnr, int * vertices) const; + void GetEdgeVertices (int enr, int & v1, int & 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<int> & edges, bool withorientation = false) const; + + ELEMENT_TYPE GetFaceType (int fnr) const; + + void GetSurfaceElementEdges (int elnr, Array<int> & edges) const; + int GetSurfaceElementFace (int elnr) const; + void GetSurfaceElementEdgeOrientations (int elnr, Array<int> & eorient) const; + int GetSurfaceElementFaceOrientation (int elnr) const; + + int GetSurfaceElementEdges (int elnr, int * edges, int * orient) const; + + const int * GetElementEdgesPtr (int elnr) const { return &edges[elnr][0]; } + const int * GetSurfaceElementEdgesPtr (int selnr) const { return &surfedges[selnr][0]; } + const int * GetSegmentElementEdgesPtr (int selnr) const { return &segedges[selnr]; } + + const int * GetElementFacesPtr (int elnr) const { return &faces[elnr][0]; } + const int * 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<int> & elements) const; + FlatArray<int> GetVertexElements (int vnr) const; + + void GetVertexSurfaceElements( int vnr, Array<int>& elements ) const; + FlatArray<int> GetVertexSurfaceElements (int vnr) const; + + + + int GetVerticesEdge ( int v1, int v2) const; + void GetSegmentVolumeElements ( int segnr, Array<int> & els ) const; + void GetSegmentSurfaceElements ( int segnr, Array<int> & els ) const; +}; + + + + + + + + + + +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: + return 5; + + case PRISM: + case PRISM12: + return 6; + + case HEX: + return 8; + + default: + cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; + } + return 0; +} + + +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: + case QUAD8: + return 4; + + case TET: + return 4; + case TET10: + return 10; + + case PYRAMID: + return 5; + + case PRISM: + case PRISM12: + return 6; + + case HEX: + return 8; + + default: + cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; + } + return 0; +} + + + +int MeshTopology :: GetNEdges (ELEMENT_TYPE et) +{ + 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: + return 8; + + case PRISM: + case PRISM12: + return 9; + + case HEX: + return 12; + + default: + cerr << "Ng_ME_GetNEdges, illegal element type " << et << endl; + } + return 0; +} + + +int MeshTopology :: GetNFaces (ELEMENT_TYPE et) +{ + 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: + return 5; + + case PRISM: + case PRISM12: + return 5; + + case HEX: + return 6; + + default: + cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; + } + return 0; +} + + + + + + +const ELEMENT_EDGE * MeshTopology :: GetEdges1 (ELEMENT_TYPE et) +{ + static int segm_edges[1][2] = + { { 1, 2 }}; + + static int trig_edges[3][2] = + { { 3, 1 }, + { 2, 3 }, + { 1, 2 }}; + + static int quad_edges[4][2] = + { { 1, 2 }, + { 3, 4 }, + { 4, 1 }, + { 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 }}; + + static int hex_edges[12][2] = + { + { 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: + return pyramid_edges; + + case PRISM: + case PRISM12: + return prism_edges; + + case HEX: + return hex_edges; + default: + cerr << "Ng_ME_GetEdges, illegal element type " << et << endl; + } + return 0; +} + + + +const ELEMENT_EDGE * MeshTopology :: GetEdges0 (ELEMENT_TYPE et) +{ + static int segm_edges[1][2] = + { { 0, 1 }}; + + static int trig_edges[3][2] = + { { 2, 0 }, + { 1, 2 }, + { 0, 1 }}; + + static int quad_edges[4][2] = + { { 0, 1 }, + { 2, 3 }, + { 3, 0 }, + { 1, 2 }}; + + + static int tet_edges[6][2] = + { { 3, 0 }, + { 3, 1 }, + { 3, 2 }, + { 0, 1 }, + { 0, 2 }, + { 1, 2 }}; + + static int prism_edges[9][2] = + { { 2, 0 }, + { 0, 1 }, + { 2, 1 }, + { 5, 3 }, + { 3, 4 }, + { 5, 4 }, + { 2, 5 }, + { 0, 3 }, + { 1, 4 }}; + + static int pyramid_edges[8][2] = + { { 0, 1 }, + { 1, 2 }, + { 0, 3 }, + { 3, 2 }, + { 0, 4 }, + { 1, 4 }, + { 2, 4 }, + { 3, 4 }}; + + static int hex_edges[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 }, + }; + + 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: + return pyramid_edges; + + case PRISM: + case PRISM12: + return prism_edges; + + case HEX: + return hex_edges; + default: + cerr << "Ng_ME_GetEdges, illegal element type " << et << endl; + } + return 0; +} + + + + + + + + + + +const ELEMENT_FACE * MeshTopology :: GetFaces1 (ELEMENT_TYPE et) +{ + static const int trig_faces[1][4] = + { { 1, 2, 3, 0 } }; + static const int quad_faces[1][4] = + { { 1, 2, 3, 4 } }; + + static const int tet_faces[4][4] = + { { 4, 2, 3, 0 }, + { 4, 3, 1, 0 }, + { 4, 1, 2, 0 }, + { 1, 3, 2, 0 } }; + + static const int prism_faces[5][4] = + { + { 1, 3, 2, 0 }, + { 4, 5, 6, 0 }, + { 3, 1, 4, 6 }, + { 1, 2, 5, 4 }, + { 2, 3, 6, 5 } + }; + + static const int pyramid_faces[5][4] = + { + { 1, 2, 5, 0 }, + { 2, 3, 5, 0 }, + { 3, 4, 5, 0 }, + { 4, 1, 5, 0 }, + { 1, 4, 3, 2 } + }; + + static const int hex_faces[6][4] = + { + { 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: + return prism_faces; + + case PYRAMID: + return pyramid_faces; + + case SEGMENT: + case SEGMENT3: + + case HEX: + return hex_faces; + + default: + cerr << "Ng_ME_GetVertices, illegal element type " << et << endl; + } + return 0; +} + + + + + +const ELEMENT_FACE * MeshTopology :: GetFaces0 (ELEMENT_TYPE et) +{ + static const int trig_faces[1][4] = + { { 0, 1, 2, -1 } }; + static const int quad_faces[1][4] = + { { 0, 1, 2, 3 } }; + + static const int tet_faces[4][4] = + { { 3, 1, 2, -1 }, + { 3, 2, 0, -1 }, + { 3, 0, 1, -1 }, + { 0, 2, 1, -1 } }; + + static const int prism_faces[5][4] = + { + { 0, 2, 1, -1 }, + { 3, 4, 5, -1 }, + { 2, 0, 3, 5 }, + { 0, 1, 4, 3 }, + { 1, 2, 5, 4 } + }; + + static const int pyramid_faces[5][4] = + { + { 0, 1, 4, -1 }, + { 1, 2, 4, -1 }, + { 2, 3, 4, -1 }, + { 3, 0, 4, -1 }, + { 0, 3, 2, 1 } + }; + + static const int hex_faces[6][4] = + { + { 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: + return prism_faces; + + case PYRAMID: + return pyramid_faces; + + case SEGMENT: + case SEGMENT3: + + case HEX: + return hex_faces; + + default: + cerr << "Ng_ME_GetVertices, illegal element type " << et << endl; + } + return 0; +} + + + + + + + + + + + + + + + + + + + + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/triarls.cpp b/contrib/Netgen/libsrc/meshing/triarls.cpp new file mode 100644 index 0000000000..d82806e9bc --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/triarls.cpp @@ -0,0 +1,468 @@ +namespace 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",\ +"(2, 3, 4);\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}; +} diff --git a/contrib/Netgen/libsrc/meshing/validate.cpp b/contrib/Netgen/libsrc/meshing/validate.cpp new file mode 100644 index 0000000000..44b983cca0 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/validate.cpp @@ -0,0 +1,591 @@ + +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + void GetPureBadness(Mesh & mesh, Array<double> & 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<np; i++) + { + backup[i] = new Point<3>(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<mesh[i].GetNP(); j++) + if(bad > 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<np; i++) + { + mesh.Point(i+1) = *backup[i]; + delete backup[i]; + } + } + + + double Validate(const Mesh & mesh, Array<ElementIndex> & bad_elements, + const Array<double> & pure_badness, + double max_worsening, const bool uselocalworsening, + Array<double> * 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<mesh[i].GetNP(); j++) + if(pure_badness[mesh[i][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<ElementIndex> & bad_elements, + const int width) + { + working_elements.Clear(); + working_points.Clear(); + + for(int i=0; i<bad_elements.Size(); i++) + { + working_elements.Set(bad_elements[i]); + const Element & el = mesh[bad_elements[i]]; + for(int j=1; j<=el.GetNP(); j++) + working_points.Set(el.PNum(j)); + } + + + for(int i=0; i<width; i++) + { + for(ElementIndex j=0; j<mesh.GetNE(); j++) + { + if(!working_elements.Test(j)) + { + const Element & el = mesh[j]; + bool set_active = false; + + for(int k=1; !set_active && k<=el.GetNP(); k++) + set_active = working_points.Test(el.PNum(k)); + + if(set_active) + working_elements.Set(j); + } + } + + for(ElementIndex j=0; j<mesh.GetNE(); j++) + { + if(working_elements.Test(j)) + { + const Element & el = mesh[j]; + for(int k=1; k<=el.GetNP(); k++) + working_points.Set(el.PNum(k)); + } + } + } + } + + + + void RepairBisection(Mesh & mesh, Array<ElementIndex> & bad_elements, + const BitArray & isnewpoint, const Refinement & refinement, + const Array<double> & pure_badness, + double max_worsening, const bool uselocalworsening, + const Array< Array<int,PointIndex::BASE>* > & 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<Point<3>* > should(np); + Array<Point<3>* > can(np); + Array<Vec<3>* > nv(np); + for(int i=0; i<np; i++) + { + nv[i] = new Vec<3>; + 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<int> 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<np; i++) + *should[i] = mesh.Point(i+1); + + + for(int i=0; i<np; i++) + { + if(isnewpoint.Test(i+PointIndex::BASE) && + //working_points.Test(i+PointIndex::BASE) && + mesh.mlbetweennodes[i+PointIndex::BASE][0] > 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<nv.Size(); i++) + *nv[i] = Vec<3>(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; i<nv.Size(); i++) + nv[i]->Normalize(); + + + 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; i<numtopimprove; i++) + { + optmesh.SwapImproveSurface(mesh,OPT_QUALITY,&working_elements,&idmaps); + optmesh.SwapImprove(mesh,OPT_QUALITY,&working_elements); + + } + + // mesh.mglevels = 1; + + + ne = mesh.GetNE(); + working_elements.SetSize(ne); + + + for (int i = 1; i <= np; i++) + mesh.Point(i) = *should.Elem(i); + + Validate(mesh,bad_elements,pure_badness, + ((uselocalworsening) ? (0.8*(max_worsening-1.) + 1.) : (0.1*(max_worsening-1.) + 1.)), + uselocalworsening); + + if(lamedge < oldlamedge || lamface < oldlamface) + numbadneighbours++; + GetWorkingArea(working_elements,working_points,mesh,bad_elements,numbadneighbours); + for(int i=1; i<=np; i++) + if(working_points.Test(i) && isboundarypoint.Test(i)) + isworkingboundary.Set(i); + else + isworkingboundary.Clear(i); + 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()); + + for (int i = 1; i <= np; i++) + mesh.Point(i) = *can.Elem(i); + } + //! + + } + + MeshingParameters dummymp; + MeshOptimize3d optmesh(dummymp); + for(int i=0; i<numtopimprove && multithread.terminate != 1; i++) + { + optmesh.SwapImproveSurface(mesh,OPT_QUALITY,NULL,&idmaps); + optmesh.SwapImprove(mesh,OPT_QUALITY); + //mesh.UpdateTopology(); + } + mesh.UpdateTopology(); + /* + if(cnttrials < 100) + { + nv = Vec3d(0,0,0); + for (int i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & sel = mesh.SurfaceElement(i); + Vec3d 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; i<nv.Size(); i++) + nv[i].Normalize(); + + + mesh.ImproveMeshJacobianOnSurface(isboundarypoint,nv,OPT_QUALITY); + mesh.CalcSurfacesOfNode(); + // smooth interior + + + for (int i = 1; i <= np; i++) + if(isboundarypoint.Test(i)) + can.Elem(i) = mesh.Point(i); + + if(optimizer2d) + optimizer2d->ProjectBoundaryPoints(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<bad_elements.Size(); i++) + { + ostrstr.str(""); + ostrstr << "bad element:" << endl + << mesh[bad_elements[i]][0] << ": " << mesh.Point(mesh[bad_elements[i]][0]) << endl + << mesh[bad_elements[i]][1] << ": " << mesh.Point(mesh[bad_elements[i]][1]) << endl + << mesh[bad_elements[i]][2] << ": " << mesh.Point(mesh[bad_elements[i]][2]) << endl + << mesh[bad_elements[i]][3] << ": " << mesh.Point(mesh[bad_elements[i]][3]); + PrintMessage(5,ostrstr.str()); + } + for (int i = 1; i <= np; i++) + mesh.Point(i) = *can.Get(i); + } + + for(int i=0; i<np; i++) + { + delete nv[i]; + delete can[i]; + delete should[i]; + } + + PopStatus(); + } +} diff --git a/contrib/Netgen/libsrc/meshing/validate.hpp b/contrib/Netgen/libsrc/meshing/validate.hpp new file mode 100644 index 0000000000..1cc01bec77 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/validate.hpp @@ -0,0 +1,21 @@ +#ifndef VALIDATE_HPP +#define VALIDATE_HPP + +namespace netgen +{ + + void GetPureBadness(Mesh & mesh, Array<double> & pure_badness, + const BitArray & isnewpoint); + double Validate(const Mesh & mesh, Array<ElementIndex> & bad_elements, + const Array<double> & pure_badness, + double max_worsening, const bool uselocalworsening, + Array<double> * quality_loss = NULL); + void RepairBisection(Mesh & mesh, Array<ElementIndex> & bad_elements, + const BitArray & isnewpoint, const Refinement & refinement, + const Array<double> & pure_badness, + double max_worsening, const bool uselocalworsening, + const Array< Array<int,PointIndex::BASE>* > & idmaps); + +} + +#endif // VALIDATE_HPP diff --git a/contrib/Netgen/libsrc/meshing/zrefine.cpp b/contrib/Netgen/libsrc/meshing/zrefine.cpp new file mode 100644 index 0000000000..0032528e2b --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/zrefine.cpp @@ -0,0 +1,740 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +#include <csg.hpp> + +namespace netgen +{ + + // find singular edges + void SelectSingularEdges (const Mesh & mesh, const CSGeometry & geom, + INDEX_2_HASHTABLE<int> & 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<int> & 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++) + { + int pi1 = el.PNum( (j+0) % 4 + 1); + int pi2 = el.PNum( (j+1) % 4 + 1); + int pi3 = el.PNum( (j+2) % 4 + 1); + int pi4 = el.PNum( (j+3) % 4 + 1); + int 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<int> & cornernodes) + { + int i, j; + int nseg = mesh.GetNSeg(); + Array<int> 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<INDEX_3> ref_uniform; + Array<INDEX_3> ref_singular; + Array<INDEX_4 > ref_slices; + + BitArray first_id(geom->identifications.Size()); + first_id.Set(); + + + INDEX_2_HASHTABLE<int> & identpts = + mesh.GetIdentifications().GetIdentifiedPoints (); + + if (&identpts) + { + 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<const CloseSurfaceIdentification*> + (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<double> & 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<EdgePointGeomInfo> epgi; + + while (1) + { + cnt++; + PrintMessage (3, "Z-Refinement, level = ", cnt); + INDEX_2_HASHTABLE<int> 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<const CloseSurfaceIdentification*> + (geom->identifications.Get(idnr)); + + + INDEX_2 edge(pi1, pi2); + edge.Sort(); + if (!refedges.Used(edge)) + { + const Array<double> & 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])); + } + } + + PrintMessage (5, "Surface elements done, NSE = ", mesh.GetNSE()); + + } + } + + + + void ZRefinement (Mesh & mesh, const NetgenGeometry * hgeom, + ZRefinementOptions & opt) + { + const CSGeometry * geom = dynamic_cast<const CSGeometry*> (hgeom); + if (!geom) return; + + INDEX_2_HASHTABLE<int> singedges(mesh.GetNSeg()); + + SelectSingularEdges (mesh, *geom, singedges, opt); + //MakePrismsSingEdge (mesh, singedges); + MakePrismsClosePoints (mesh); + + RefinePrisms (mesh, geom, opt); + } + + + + ZRefinementOptions :: ZRefinementOptions() + { + minref = 0; + } + +} diff --git a/contrib/Netgen/libsrc/occ/Makefile.am b/contrib/Netgen/libsrc/occ/Makefile.am new file mode 100644 index 0000000000..a3c7bd4b37 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Makefile.am @@ -0,0 +1,28 @@ +noinst_HEADERS = occgeom.hpp occmeshsurf.hpp \ +Partition_Inter2d.hxx Partition_Loop2d.hxx Partition_Loop.hxx \ +Partition_Inter3d.hxx Partition_Loop3d.hxx Partition_Spliter.hxx \ +Partition_Inter2d.ixx Partition_Loop2d.ixx Partition_Loop.ixx \ +Partition_Inter3d.ixx Partition_Loop3d.ixx Partition_Spliter.ixx \ +Partition_Inter2d.jxx Partition_Loop2d.jxx Partition_Loop.jxx \ +Partition_Inter3d.jxx Partition_Loop3d.jxx Partition_Spliter.jxx \ +utilities.h + + +AM_CPPFLAGS = -I$(top_srcdir)/libsrc/include $(OCCFLAGS) $(TCL_INCLUDES) + +# $(OCC_INC_FLAG) + +METASOURCES = AUTO + +lib_LTLIBRARIES = libocc.la liboccvis.la + +libocc_la_SOURCES = 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 + +libocc_la_LIBADD = $(OCCLIBS) + +liboccvis_la_SOURCES = occpkg.cpp vsocc.cpp +liboccvis_la_LIBADD = libocc.la + + diff --git a/contrib/Netgen/libsrc/occ/Partition_Inter2d.cxx b/contrib/Netgen/libsrc/occ/Partition_Inter2d.cxx new file mode 100644 index 0000000000..700955276f --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Inter2d.cxx @@ -0,0 +1,678 @@ +#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 <BRepAdaptor_Curve.hxx> +#include <BRepAlgo_AsDes.hxx> +#include <BRepLib_MakeVertex.hxx> +#include <BRep_Builder.hxx> +#include <BRep_Tool.hxx> +#include <Geom_Surface.hxx> +#include <Precision.hxx> +#include <TopExp.hxx> +#include <TopExp_Explorer.hxx> +#include <TopOpeBRepDS_Transition.hxx> +#include <TopOpeBRep_EdgesIntersector.hxx> +#include <TopOpeBRep_Point2d.hxx> +#include <TopTools_ListIteratorOfListOfShape.hxx> +#include <TopTools_ListOfShape.hxx> +#include <TopTools_MapIteratorOfMapOfShape.hxx> +#include <TopTools_MapOfShape.hxx> +#include <TopoDS.hxx> +#include <TopoDS_Edge.hxx> +#include <TopoDS_Vertex.hxx> +#include <gp_Pnt.hxx> + +#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 <VertList> having parameter on +// <E> closest to <f> or <l>. <isFirst> is True if +// found vertex is closer to <f>. <DU> 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 <LV1> +//======================================================================= + +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 <F> . 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 diff --git a/contrib/Netgen/libsrc/occ/Partition_Inter2d.hxx b/contrib/Netgen/libsrc/occ/Partition_Inter2d.hxx new file mode 100644 index 0000000000..cfd4a9ac0a --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Inter2d.hxx @@ -0,0 +1,110 @@ +// 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 _Handle_BRepAlgo_AsDes_HeaderFile +#include <Handle_BRepAlgo_AsDes.hxx> +#endif +#ifndef _Standard_Real_HeaderFile +#include <Standard_Real.hxx> +#endif +#ifndef _Standard_Boolean_HeaderFile +#include <Standard_Boolean.hxx> +#endif +class BRepAlgo_AsDes; +class TopoDS_Face; +class TopTools_MapOfShape; +class TopoDS_Vertex; +class TopTools_ListOfShape; +class TopoDS_Edge; + + +#ifndef _Standard_HeaderFile +#include <Standard.hxx> +#endif +#ifndef _Standard_Macro_HeaderFile +#include <Standard_Macro.hxx> +#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 diff --git a/contrib/Netgen/libsrc/occ/Partition_Inter2d.ixx b/contrib/Netgen/libsrc/occ/Partition_Inter2d.ixx new file mode 100644 index 0000000000..5dbe719329 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Inter2d.ixx @@ -0,0 +1,32 @@ +// 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 <climits> +#include "Partition_Inter2d.jxx" + + + + diff --git a/contrib/Netgen/libsrc/occ/Partition_Inter2d.jxx b/contrib/Netgen/libsrc/occ/Partition_Inter2d.jxx new file mode 100644 index 0000000000..2d08527511 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Inter2d.jxx @@ -0,0 +1,50 @@ +// 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 <mystdlib.h> // netgen headers + + +#ifndef _BRepAlgo_AsDes_HeaderFile +#include <BRepAlgo_AsDes.hxx> +#endif +#ifndef _TopoDS_Face_HeaderFile +#include <TopoDS_Face.hxx> +#endif +#ifndef _TopTools_MapOfShape_HeaderFile +#include <TopTools_MapOfShape.hxx> +#endif +#ifndef _TopoDS_Vertex_HeaderFile +#include <TopoDS_Vertex.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopoDS_Edge_HeaderFile +#include <TopoDS_Edge.hxx> +#endif +#ifndef _Partition_Inter2d_HeaderFile +#include "Partition_Inter2d.hxx" +#endif diff --git a/contrib/Netgen/libsrc/occ/Partition_Inter3d.cxx b/contrib/Netgen/libsrc/occ/Partition_Inter3d.cxx new file mode 100644 index 0000000000..a47ff2dff5 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Inter3d.cxx @@ -0,0 +1,947 @@ +#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 <climits> + +#include "Partition_Inter2d.hxx" +#include "Partition_Inter3d.ixx" +#include "utilities.h" + +#include <BRepAlgo_AsDes.hxx> +#include <BRepAlgo_Image.hxx> +#include <BRepLib.hxx> +#include <BRepOffset_Tool.hxx> +#include <BRep_Builder.hxx> +#include <BRep_Tool.hxx> + +#include <TopExp.hxx> +#include <TopExp_Explorer.hxx> + +#include <TopOpeBRepTool_BoxSort.hxx> +#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx> +#include <TopTools_ListIteratorOfListOfShape.hxx> +#include <TopTools_ListOfShape.hxx> +#include <TopoDS.hxx> +#include <TopoDS_Compound.hxx> +#include <TopoDS_Edge.hxx> +#include <TopoDS_Face.hxx> +#include <TopoDS_Vertex.hxx> + +#ifdef DEB +#include <DBRep.hxx> +#endif + +#include <BRepLib_MakeVertex.hxx> +#include <BRepTools.hxx> +#include <Extrema_ExtPS.hxx> +#include <Extrema_POnSurf.hxx> +#include <Geom2dAPI_ProjectPointOnCurve.hxx> +#include <Geom2d_Curve.hxx> +#include <GeomAPI_ProjectPointOnCurve.hxx> +#include <GeomAdaptor_Surface.hxx> +#include <Geom_Curve.hxx> +#include <Geom_RectangularTrimmedSurface.hxx> +#include <Geom_SphericalSurface.hxx> +#include <Geom_Surface.hxx> +#include <Geom_TrimmedCurve.hxx> +#include <Precision.hxx> +#include <TColStd_MapOfInteger.hxx> +#include <TopOpeBRepBuild_Builder.hxx> +#include <TopOpeBRepDS_BuildTool.hxx> +#include <TopOpeBRepDS_CurveExplorer.hxx> +#include <TopOpeBRepDS_HDataStructure.hxx> +#include <TopOpeBRepDS_Interference.hxx> +#include <TopOpeBRepDS_PointIterator.hxx> +#include <TopOpeBRepDS_Transition.hxx> +#include <TopOpeBRepTool_CurveTool.hxx> +#include <TopOpeBRepTool_GeomTool.hxx> +#include <TopOpeBRepTool_OutCurveType.hxx> +#include <TopOpeBRep_DSFiller.hxx> +#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx> +#include <stdio.h> + +//======================================================================= +//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 nontheless 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 (" CANT 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 diff --git a/contrib/Netgen/libsrc/occ/Partition_Inter3d.hxx b/contrib/Netgen/libsrc/occ/Partition_Inter3d.hxx new file mode 100644 index 0000000000..d8be2c5983 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Inter3d.hxx @@ -0,0 +1,143 @@ +// 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 _Handle_BRepAlgo_AsDes_HeaderFile +#include <Handle_BRepAlgo_AsDes.hxx> +#endif +#ifndef _TopTools_DataMapOfShapeListOfShape_HeaderFile +#include <TopTools_DataMapOfShapeListOfShape.hxx> +#endif +#ifndef _TopTools_MapOfShape_HeaderFile +#include <TopTools_MapOfShape.hxx> +#endif +#ifndef _TopTools_DataMapOfShapeShape_HeaderFile +#include <TopTools_DataMapOfShapeShape.hxx> +#endif +#ifndef _Standard_Boolean_HeaderFile +#include <Standard_Boolean.hxx> +#endif +class BRepAlgo_AsDes; +class TopTools_ListOfShape; +class TopTools_DataMapOfShapeShape; +class TopoDS_Face; +class TopTools_MapOfShape; +class TopoDS_Shape; +class TopoDS_Vertex; +class TopoDS_Edge; + + +#ifndef _Standard_HeaderFile +#include <Standard.hxx> +#endif +#ifndef _Standard_Macro_HeaderFile +#include <Standard_Macro.hxx> +#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 diff --git a/contrib/Netgen/libsrc/occ/Partition_Inter3d.ixx b/contrib/Netgen/libsrc/occ/Partition_Inter3d.ixx new file mode 100644 index 0000000000..0775cc99c9 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Inter3d.ixx @@ -0,0 +1,31 @@ +// 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" + + + + diff --git a/contrib/Netgen/libsrc/occ/Partition_Inter3d.jxx b/contrib/Netgen/libsrc/occ/Partition_Inter3d.jxx new file mode 100644 index 0000000000..5804ba81e8 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Inter3d.jxx @@ -0,0 +1,53 @@ +// 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 <BRepAlgo_AsDes.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_DataMapOfShapeShape_HeaderFile +#include <TopTools_DataMapOfShapeShape.hxx> +#endif +#ifndef _TopoDS_Face_HeaderFile +#include <TopoDS_Face.hxx> +#endif +#ifndef _TopTools_MapOfShape_HeaderFile +#include <TopTools_MapOfShape.hxx> +#endif +#ifndef _TopoDS_Shape_HeaderFile +#include <TopoDS_Shape.hxx> +#endif +#ifndef _TopoDS_Vertex_HeaderFile +#include <TopoDS_Vertex.hxx> +#endif +#ifndef _TopoDS_Edge_HeaderFile +#include <TopoDS_Edge.hxx> +#endif +#ifndef _Partition_Inter3d_HeaderFile +#include "Partition_Inter3d.hxx" +#endif diff --git a/contrib/Netgen/libsrc/occ/Partition_Loop.cxx b/contrib/Netgen/libsrc/occ/Partition_Loop.cxx new file mode 100644 index 0000000000..0511bfd2eb --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Loop.cxx @@ -0,0 +1,473 @@ +#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 <cstdio> +#include <climits> + +#include "Partition_Loop.ixx" + +#include "utilities.h" + +#include <BRep_Builder.hxx> +#include <BRepAlgo_FaceRestrictor.hxx> +#include <BRep_Tool.hxx> + +#include <Geom2d_Curve.hxx> +#include <Geom_Surface.hxx> + +#include <TopTools_SequenceOfShape.hxx> +#include <TopTools_ListIteratorOfListOfShape.hxx> +#include <TopTools_MapOfShape.hxx> +#include <TopTools_MapIteratorOfMapOfShape.hxx> +#include <TopTools_MapOfOrientedShape.hxx> +#include <TopTools_DataMapOfShapeShape.hxx> +#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx> + +#include <gp_Pnt.hxx> +#include <gp_Pnt2d.hxx> + +#include <TopoDS.hxx> +#include <TopoDS_Vertex.hxx> +#include <TopoDS_Wire.hxx> +#include <TopoDS_Iterator.hxx> + +#include <Precision.hxx> +#include <BRep_TVertex.hxx> +#include <BRep_TEdge.hxx> + +#include <TopExp.hxx> +#include <TopExp_Explorer.hxx> + +static char* name = new char[100]; +static int nbe = 0; + +//======================================================================= +//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<d) { d=d1;} + } + dist = d ; + return dist; +} + +//======================================================================= +//function : SelectEdge +//purpose : Find the edge <NE> connected <CE> by the vertex <CV> in the list <LE>. +// <NE> Is erased of the list. If <CE> is too in the list <LE> +// 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 edges differents 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 = - 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 diff --git a/contrib/Netgen/libsrc/occ/Partition_Loop.hxx b/contrib/Netgen/libsrc/occ/Partition_Loop.hxx new file mode 100644 index 0000000000..56e05e260b --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Loop.hxx @@ -0,0 +1,118 @@ +// 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 <TopoDS_Face.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_DataMapOfShapeListOfShape_HeaderFile +#include <TopTools_DataMapOfShapeListOfShape.hxx> +#endif +class TopoDS_Face; +class TopoDS_Edge; +class TopTools_ListOfShape; + + +#ifndef _Standard_HeaderFile +#include <Standard.hxx> +#endif +#ifndef _Standard_Macro_HeaderFile +#include <Standard_Macro.hxx> +#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 diff --git a/contrib/Netgen/libsrc/occ/Partition_Loop.ixx b/contrib/Netgen/libsrc/occ/Partition_Loop.ixx new file mode 100644 index 0000000000..1c40e72540 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Loop.ixx @@ -0,0 +1,31 @@ +// 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" + + + + diff --git a/contrib/Netgen/libsrc/occ/Partition_Loop.jxx b/contrib/Netgen/libsrc/occ/Partition_Loop.jxx new file mode 100644 index 0000000000..dd86f05c3d --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Loop.jxx @@ -0,0 +1,41 @@ +// 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 <TopoDS_Face.hxx> +#endif +#ifndef _TopoDS_Edge_HeaderFile +#include <TopoDS_Edge.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_DataMapOfShapeShape_HeaderFile +#include <TopTools_DataMapOfShapeShape.hxx> +#endif +#ifndef _Partition_Loop_HeaderFile +#include "Partition_Loop.hxx" +#endif diff --git a/contrib/Netgen/libsrc/occ/Partition_Loop2d.cxx b/contrib/Netgen/libsrc/occ/Partition_Loop2d.cxx new file mode 100644 index 0000000000..40872bd930 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Loop2d.cxx @@ -0,0 +1,1145 @@ +#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 <climits> +#include "Partition_Loop2d.ixx" + +#include "utilities.h" +#include <stdio.h> + +#include <BRepAdaptor_Curve2d.hxx> +#include <BRepAdaptor_Surface.hxx> +#include <BRepAlgo_AsDes.hxx> +#include <BRepAlgo_FaceRestrictor.hxx> +#include <BRepOffset_DataMapOfShapeReal.hxx> +#include <BRepTopAdaptor_FClass2d.hxx> +#include <BRep_Builder.hxx> +#include <BRep_Tool.hxx> +#include <Geom2dInt_GInter.hxx> +#include <Geom2d_Curve.hxx> +#include <IntRes2d_IntersectionPoint.hxx> +#include <Precision.hxx> +#include <TColStd_MapOfInteger.hxx> +#include <TColStd_SequenceOfReal.hxx> +#include <TopExp.hxx> +#include <TopExp_Explorer.hxx> +#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx> +#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx> +#include <TopTools_DataMapOfShapeInteger.hxx> +// #include <TopTools_DataMapOfShapeReal.hxx> V6.5 +#include <TopTools_DataMapOfShapeShape.hxx> +#include <TopTools_IndexedMapOfShape.hxx> +#include <TopTools_ListIteratorOfListOfShape.hxx> +#include <TopTools_MapIteratorOfMapOfShape.hxx> +#include <TopTools_MapOfOrientedShape.hxx> +#include <TopTools_MapOfShape.hxx> +#include <TopTools_SequenceOfShape.hxx> +#include <TopoDS.hxx> +#include <TopoDS_Iterator.hxx> +#include <TopoDS_Vertex.hxx> +#include <TopoDS_Wire.hxx> +#include <gp_Pnt.hxx> +#include <gp_Pnt2d.hxx> + +//======================================================================= +//function : Partition_Loop2d +//purpose : +//======================================================================= + +Partition_Loop2d::Partition_Loop2d() +{ +} + +//======================================================================= +//function : Init +//purpose : Init with <F> the set of edges must have +// pcurves on <F>. +//======================================================================= + +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 <E> 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 untill 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 <LE> the edge <NE> connected with <CE> by +// the vertex <CV>. +// <NE> is removed from the list. If <CE> is in <LE> +// 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 edges differents 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 * 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 (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 <EM> all edges reachable from <E> +//======================================================================= + +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 <CE> with <DE> and +// select an edge with its parameter closest to found one. +// Return new degenerated edge trimming <DE> 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 <DegEdge> with edges bound to its vertex in <MVE> +// and store intersection parameter on <DegEdge> in +// <USeq> as well as the edges them-self in <EdgesSeq>. +// Bind <DegEdgeIndex> to vertex of <DegEdge> in <MVDEI> +//======================================================================= + +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() ); + // 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 doulbe 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 <outerEM>, 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 <WiresToFaces> 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 <WL> to <EqWL> 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. +// <EdgeImage> serves to find original edge by new +// one. <Section> 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 diff --git a/contrib/Netgen/libsrc/occ/Partition_Loop2d.hxx b/contrib/Netgen/libsrc/occ/Partition_Loop2d.hxx new file mode 100644 index 0000000000..bdf1c2531d --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Loop2d.hxx @@ -0,0 +1,106 @@ +// 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 <TopoDS_Face.hxx> +#endif +#ifndef _TopAbs_Orientation_HeaderFile +#include <TopAbs_Orientation.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_MapOfShape_HeaderFile +#include <TopTools_MapOfShape.hxx> +#endif +class TopoDS_Face; +class TopoDS_Edge; +class TopTools_ListOfShape; +class BRepAlgo_Image; + + +#ifndef _Standard_HeaderFile +#include <Standard.hxx> +#endif +#ifndef _Standard_Macro_HeaderFile +#include <Standard_Macro.hxx> +#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 diff --git a/contrib/Netgen/libsrc/occ/Partition_Loop2d.ixx b/contrib/Netgen/libsrc/occ/Partition_Loop2d.ixx new file mode 100644 index 0000000000..2d35fd5c71 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Loop2d.ixx @@ -0,0 +1,14 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Partition_Loop2d.ixx +// Module : GEOM + +#include "Partition_Loop2d.jxx" + + + + diff --git a/contrib/Netgen/libsrc/occ/Partition_Loop2d.jxx b/contrib/Netgen/libsrc/occ/Partition_Loop2d.jxx new file mode 100644 index 0000000000..555c16c809 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Loop2d.jxx @@ -0,0 +1,24 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Partition_Loop2d.jxx +// Module : GEOM + +#ifndef _TopoDS_Face_HeaderFile +#include <TopoDS_Face.hxx> +#endif +#ifndef _TopoDS_Edge_HeaderFile +#include <TopoDS_Edge.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _BRepAlgo_Image_HeaderFile +#include <BRepAlgo_Image.hxx> +#endif +#ifndef _Partition_Loop2d_HeaderFile +#include "Partition_Loop2d.hxx" +#endif diff --git a/contrib/Netgen/libsrc/occ/Partition_Loop3d.cxx b/contrib/Netgen/libsrc/occ/Partition_Loop3d.cxx new file mode 100644 index 0000000000..3e9acc3ccb --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Loop3d.cxx @@ -0,0 +1,356 @@ +#ifdef OCCGEOMETRY + +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Partition_Loop3d.cxx +// Module : GEOM + +//using namespace std; +#include <climits> +#include "Partition_Loop3d.ixx" + +#include <TopExp_Explorer.hxx> +#include <TopExp.hxx> +#include <BRep_Builder.hxx> +#include <TopTools_MapOfShape.hxx> +#include <TopTools_ListIteratorOfListOfShape.hxx> +#include <TopoDS_Shell.hxx> +#include <TopoDS_Iterator.hxx> +#include <TopoDS.hxx> +#include <TopTools_MapIteratorOfMapOfShape.hxx> +#include <gp_Vec.hxx> +#include <gp_Pnt.hxx> +#include <Geom2d_Curve.hxx> +#include <BRep_Tool.hxx> +#include <Geom_Surface.hxx> +#include <gp_Pnt2d.hxx> +#include <gp_Vec2d.hxx> +#include <gp_Dir2d.hxx> +#include <Geom_Curve.hxx> + +//======================================================================= +//function : Partition_Loop3d +//purpose : +//======================================================================= + +Partition_Loop3d::Partition_Loop3d() +{ +} + +//======================================================================= +//function : AddConstFaces +//purpose : Add faces of <S> 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 <S> 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. +// <AvoidFacesMap> 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 <F2> is inside <F1> by edge <E>. +// if <CountDot>, compute <Dot>: 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 diff --git a/contrib/Netgen/libsrc/occ/Partition_Loop3d.hxx b/contrib/Netgen/libsrc/occ/Partition_Loop3d.hxx new file mode 100644 index 0000000000..52abd115e9 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Loop3d.hxx @@ -0,0 +1,102 @@ +// 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 <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_IndexedDataMapOfShapeListOfShape_HeaderFile +#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> +#endif +#ifndef _Standard_Boolean_HeaderFile +#include <Standard_Boolean.hxx> +#endif +#ifndef _Standard_Real_HeaderFile +#include <Standard_Real.hxx> +#endif +class TopoDS_Shape; +class TopTools_ListOfShape; +class TopTools_MapOfOrientedShape; +class TopoDS_Edge; +class TopoDS_Face; +class gp_Vec; + + +#ifndef _Standard_HeaderFile +#include <Standard.hxx> +#endif +#ifndef _Standard_Macro_HeaderFile +#include <Standard_Macro.hxx> +#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 diff --git a/contrib/Netgen/libsrc/occ/Partition_Loop3d.ixx b/contrib/Netgen/libsrc/occ/Partition_Loop3d.ixx new file mode 100644 index 0000000000..a661b3242d --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Loop3d.ixx @@ -0,0 +1,14 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Partition_Loop3d.ixx +// Module : GEOM + +#include "Partition_Loop3d.jxx" + + + + diff --git a/contrib/Netgen/libsrc/occ/Partition_Loop3d.jxx b/contrib/Netgen/libsrc/occ/Partition_Loop3d.jxx new file mode 100644 index 0000000000..9b654f41bb --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Loop3d.jxx @@ -0,0 +1,30 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Partition_Loop3d.jxx +// Module : GEOM + +#ifndef _TopoDS_Shape_HeaderFile +#include <TopoDS_Shape.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_MapOfOrientedShape_HeaderFile +#include <TopTools_MapOfOrientedShape.hxx> +#endif +#ifndef _TopoDS_Edge_HeaderFile +#include <TopoDS_Edge.hxx> +#endif +#ifndef _TopoDS_Face_HeaderFile +#include <TopoDS_Face.hxx> +#endif +#ifndef _gp_Vec_HeaderFile +#include <gp_Vec.hxx> +#endif +#ifndef _Partition_Loop3d_HeaderFile +#include "Partition_Loop3d.hxx" +#endif diff --git a/contrib/Netgen/libsrc/occ/Partition_Spliter.cxx b/contrib/Netgen/libsrc/occ/Partition_Spliter.cxx new file mode 100644 index 0000000000..97bd8e3322 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Spliter.cxx @@ -0,0 +1,2168 @@ +#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 <climits> +#include "Partition_Inter2d.hxx" +#include "Partition_Inter3d.hxx" +#include "Partition_Loop2d.hxx" +#include "Partition_Loop3d.hxx" +#include "Partition_Spliter.ixx" + +#include "utilities.h" + +#include <Precision.hxx> +#include <TopAbs_Orientation.hxx> +#include <TopExp.hxx> +#include <TopExp_Explorer.hxx> + +#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx> +#include <TopTools_DataMapOfShapeListOfShape.hxx> +#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> +#include <TopTools_IndexedMapOfShape.hxx> +#include <TopTools_ListIteratorOfListOfShape.hxx> +#include <TopTools_ListOfShape.hxx> +#include <TopTools_MapIteratorOfMapOfShape.hxx> +#include <TopTools_SequenceOfShape.hxx> + +#include <Geom2d_Curve.hxx> +#include <Geom_Curve.hxx> +#include <Geom_Surface.hxx> +#include <Geom_TrimmedCurve.hxx> +#include <gp_Pnt.hxx> +#include <gp_Pnt2d.hxx> +#include <gp_Vec.hxx> + +#include <TopoDS.hxx> +#include <TopoDS_Compound.hxx> +#include <TopoDS_Edge.hxx> +#include <TopoDS_Face.hxx> +#include <TopoDS_Iterator.hxx> +#include <TopoDS_Shell.hxx> +#include <TopoDS_Solid.hxx> +#include <TopoDS_Vertex.hxx> +#include <TopoDS_Wire.hxx> + +#include <BRepBndLib.hxx> +#include <BRepClass3d_SolidClassifier.hxx> +#include <BRepLib.hxx> +#include <BRep_Tool.hxx> + +#include <Extrema_ExtPC.hxx> +#include <GeomAdaptor_Curve.hxx> +#include <TopOpeBRepTool_CurveTool.hxx> + +#ifdef DEB +//# define PART_PERF +#endif + +#ifdef PART_PERF +# include <OSD_Chronometer.hxx> +#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 <theShape>. +// <theShape> is an object shape. +// <CheckClosed> makes avoid faces that do not form a +// closed shell +// <All> 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 not split 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. +// <addSame>==True makes consider same edges as equal +// Put in <AllEqMap> 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 (; i<nbi && ok; ++i) { + Extrema.Perform( C2->Value( 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 not splitted 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 (" CANT 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 <S> is a tool shape. Prepare tool +// faces of <S> 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 adges + 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 diff --git a/contrib/Netgen/libsrc/occ/Partition_Spliter.hxx b/contrib/Netgen/libsrc/occ/Partition_Spliter.hxx new file mode 100644 index 0000000000..f29917a3e1 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Spliter.hxx @@ -0,0 +1,150 @@ +// 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 _TopAbs_ShapeEnum_HeaderFile +#include <TopAbs_ShapeEnum.hxx> +#endif +#ifndef _TopoDS_Compound_HeaderFile +#include <TopoDS_Compound.hxx> +#endif +#ifndef _BRep_Builder_HeaderFile +#include <BRep_Builder.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_MapOfShape_HeaderFile +#include <TopTools_MapOfShape.hxx> +#endif +#ifndef _TopTools_DataMapOfShapeShape_HeaderFile +#include <TopTools_DataMapOfShapeShape.hxx> +#endif +#ifndef _Handle_BRepAlgo_AsDes_HeaderFile +#include <Handle_BRepAlgo_AsDes.hxx> +#endif +#ifndef _BRepAlgo_Image_HeaderFile +#include <BRepAlgo_Image.hxx> +#endif +#ifndef _Partition_Inter3d_HeaderFile +#include "Partition_Inter3d.hxx" +#endif +#ifndef _TopTools_MapOfOrientedShape_HeaderFile +#include <TopTools_MapOfOrientedShape.hxx> +#endif +#ifndef _Standard_Boolean_HeaderFile +#include <Standard_Boolean.hxx> +#endif +class BRepAlgo_AsDes; +class TopoDS_Shape; +class TopTools_ListOfShape; +class TopoDS_Edge; + + +#ifndef _Standard_HeaderFile +#include <Standard.hxx> +#endif +#ifndef _Standard_Macro_HeaderFile +#include <Standard_Macro.hxx> +#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 diff --git a/contrib/Netgen/libsrc/occ/Partition_Spliter.ixx b/contrib/Netgen/libsrc/occ/Partition_Spliter.ixx new file mode 100644 index 0000000000..ee82594685 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Spliter.ixx @@ -0,0 +1,31 @@ +// 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" + + + + diff --git a/contrib/Netgen/libsrc/occ/Partition_Spliter.jxx b/contrib/Netgen/libsrc/occ/Partition_Spliter.jxx new file mode 100644 index 0000000000..bf8622c93a --- /dev/null +++ b/contrib/Netgen/libsrc/occ/Partition_Spliter.jxx @@ -0,0 +1,41 @@ +// 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 <BRepAlgo_AsDes.hxx> +#endif +#ifndef _TopoDS_Shape_HeaderFile +#include <TopoDS_Shape.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopoDS_Edge_HeaderFile +#include <TopoDS_Edge.hxx> +#endif +#ifndef _Partition_Spliter_HeaderFile +#include "Partition_Spliter.hxx" +#endif diff --git a/contrib/Netgen/libsrc/occ/occconstruction.cpp b/contrib/Netgen/libsrc/occ/occconstruction.cpp new file mode 100644 index 0000000000..2945a1470a --- /dev/null +++ b/contrib/Netgen/libsrc/occ/occconstruction.cpp @@ -0,0 +1,157 @@ + +#ifdef OCCGEOMETRY + +#include <mystdlib.h> +#include <occgeom.hpp> +#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 <GC_MakeSegment.hxx> +#include <BRepBuilderAPI_MakeEdge.hxx> +#include <BRepBuilderAPI_MakeWire.hxx> +#include <BRepPrimAPI_MakeBox.hxx> +// #include <BRep_Builder.hxx> +#include <TopoDS_Builder.hxx> +#include <BRepAlgoAPI_Cut.hxx> +#include <BRepAlgoAPI_Common.hxx> +#include <BRepAlgoAPI_Fuse.hxx> +#include <BRepAlgoAPI_Section.hxx> +#include <BRepOffsetAPI_Sewing.hxx> +//#include <BRepAlgo_Sewing.hxx> +#include <BRepOffsetAPI_MakeOffsetShape.hxx> +#include <ShapeFix_Shape.hxx> +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 diff --git a/contrib/Netgen/libsrc/occ/occgenmesh.cpp b/contrib/Netgen/libsrc/occ/occgenmesh.cpp new file mode 100644 index 0000000000..aefec84412 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/occgenmesh.cpp @@ -0,0 +1,1460 @@ +#ifdef OCCGEOMETRY + +#include <mystdlib.h> +#include <occgeom.hpp> +#include <meshing.hpp> + + +namespace netgen +{ + +#include "occmeshsurf.hpp" + +#define TCL_OK 0 +#define TCL_ERROR 1 + +#define DIVIDEEDGESECTIONS 1000 +#define IGNORECURVELENGTH 1e-4 +#define VSMALL 1e-10 + + + 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<MeshPoint> & ps, + Array<double> & 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<int> 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)); + } + // 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 <MeshPoint> mp; + Array <double> params; + + DivideEdge (edge, mp, params, mesh); + + Array <int> 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<int> 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 occured 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 OCCURED 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 int timer_opt2d = NgProfiler::CreateTimer ("Optimization 2D"); + NgProfiler::StartTimer (timer_opt2d); + + 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(); + + NgProfiler::StopTimer (timer_opt2d); + + multithread.task = savetask; + } + + + + void OCCSetLocalMeshSize(OCCGeometry & geom, Mesh & mesh) + { + mesh.SetGlobalH (mparam.maxh); + mesh.SetMinimalH (mparam.minh); + + Array<double> 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 maxedgelen = 0; + double minedgelen = 1e99; + + 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 < IGNORECURVELENGTH) + { + (*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()) continue; + + 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<Line> lines(sections*nedges); + + Box3dTree* searchtree = + new Box3dTree (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<int> 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, Mesh *& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend) + { + multithread.percent = 0; + + if (perfstepsstart <= MESHCONST_ANALYSE) + { + delete mesh; + mesh = new Mesh(); + mesh->geomtype = Mesh::GEOM_OCC; + + OCCSetLocalMeshSize(geom,*mesh); + } + + if (multithread.terminate || perfstepsend <= MESHCONST_ANALYSE) + return TCL_OK; + + if (perfstepsstart <= MESHCONST_MESHEDGES) + { + OCCFindEdges (geom, *mesh); + + /* + cout << "Removing redundant points" << endl; + + int i, j; + int np = mesh->GetNP(); + Array<int> 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 || perfstepsend <= MESHCONST_MESHEDGES) + return TCL_OK; + + if (perfstepsstart <= MESHCONST_MESHSURFACE) + { + OCCMeshSurface (geom, *mesh, 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 || perfstepsend <= MESHCONST_OPTSURFACE) + return TCL_OK; + + if (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 || perfstepsend <= MESHCONST_MESHVOLUME) + return TCL_OK; + + if (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; + + return TCL_OK; + } +} + +#endif diff --git a/contrib/Netgen/libsrc/occ/occgeom.cpp b/contrib/Netgen/libsrc/occ/occgeom.cpp new file mode 100644 index 0000000000..a363607b64 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/occgeom.cpp @@ -0,0 +1,1608 @@ + +#ifdef OCCGEOMETRY + +#include <mystdlib.h> +#include <occgeom.hpp> +#include "ShapeAnalysis_ShapeTolerance.hxx" +#include "ShapeAnalysis_ShapeContents.hxx" +#include "ShapeAnalysis_CheckSmallFace.hxx" +#include "ShapeAnalysis_DataMapOfShapeListOfReal.hxx" +#include "ShapeAnalysis_Surface.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" + + +namespace netgen +{ + 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, false); + } + 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)" <<endl; + else if(sff->Status(ShapeExtend_DONE2)) + cout << "(orientation of wires fixed)" <<endl; + else if(sff->Status(ShapeExtend_DONE3)) + cout << "(missing seam added)" <<endl; + else if(sff->Status(ShapeExtend_DONE4)) + cout << "(small area wire removed)" <<endl; + else if(sff->Status(ShapeExtend_DONE5)) + cout << "(natural bounds added)" <<endl; + TopoDS_Face newface = sff->Face(); + + rebuild->Replace(face, newface, Standard_False); + } + + // 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, false); + } + 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, Standard_False); + } + + //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, false); + } + } + } + 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, false); + } + 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, false); + } + 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, Standard_False); + 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, Standard_False); + + 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; + BRepBndLib::Add (shape, bb); + + 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; + } + + + + // Philippose - 23/02/2009 + /* Special IGES File load function including the ability + to extract individual surface colours via the extended + OpenCascade XDE and XCAF Feature set. + */ + OCCGeometry *LoadOCC_IGES(const char *filename) + { + OCCGeometry *occgeo; + occgeo = new OCCGeometry; + + // Initiate a dummy XCAF Application to handle the IGES XCAF Document + static Handle_XCAFApp_Application dummy_app = XCAFApp_Application::GetApplication(); + + // Create an XCAF Document to contain the IGES file itself + Handle_TDocStd_Document iges_doc; + + // Check if a IGES 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,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) + { + delete occgeo; + return NULL; + } + + // 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 compund 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; + + // 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); + + Standard_Integer stat = reader.ReadFile((char*)filename); + + if(stat != IFSelect_RetDone) + { + delete occgeo; + return NULL; + } + + 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); + + 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<char*> (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); + } + } + + + + 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 streched 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 <double> edgeLengths; + Array <int> 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 (Mesh*& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend) + { + return OCCGenerateMesh (*this, mesh, mparam, perfstepsstart, perfstepsend); + } + + + + + const Refinement & OCCGeometry :: GetRefinement () const + { + return * new OCCRefinementSurfaces (*this); + } + + + + + OCCParameters :: OCCParameters() + { + resthcloseedgefac = 1; + resthcloseedgeenable = 1; + } + + + + + void OCCParameters :: Print(ostream & ost) const + { + ost << "OCC Parameters:" << endl + << "close edges: " << resthcloseedgeenable + << ", fac = " << resthcloseedgefac << endl; + } + + + + + OCCParameters occparam; + +} + + +#endif diff --git a/contrib/Netgen/libsrc/occ/occgeom.hpp b/contrib/Netgen/libsrc/occ/occgeom.hpp new file mode 100644 index 0000000000..16b2f761fc --- /dev/null +++ b/contrib/Netgen/libsrc/occ/occgeom.hpp @@ -0,0 +1,451 @@ +#ifndef FILE_OCCGEOM +#define FILE_OCCGEOM + +/* *************************************************************************/ +/* File: occgeom.hpp */ +/* Author: Robert Gaisbauer */ +/* Date: 26. May 03 */ +/* *************************************************************************/ + +#ifdef OCCGEOMETRY + +#include <meshing.hpp> + +#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<bool> fsingular, esingular, vsingular; + Box<3> boundingbox; + + // 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<int> facemeshstatus; + + // Philippose - 15/01/2009 + // Maximum mesh size for a given face + // (Used to explicitly define mesh size limits on individual faces) + Array<double> face_maxh; + + // Philippose - 14/01/2010 + // Boolean array to detect whether a face has been explicitly modified + // by the user or not + Array<bool> 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<bool> face_sel_status; + + Array<EntityVisualizationCode> 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(); + } + + + virtual void Save (string filename) const; + + + 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); + } + + void CalcBoundingBox (); + void BuildVisualizationMesh (double deflection); + + void RecursiveTopologyTree (const TopoDS_Shape & sh, + stringstream & str, + TopAbs_ShapeEnum l, + bool free, + const char * lname); + + void GetTopologyTree (stringstream & str); + + void PrintNrShapes (); + + void CheckIrregularEntities (stringstream & str); + + void SewFaces(); + + void MakeSolid(); + + 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(); + } + + void GetUnmeshedFaceInfo (stringstream & str); + void GetNotDrawableFaces (stringstream & str); + bool ErrorInSurfaceMeshing (); + + void WriteOCC_STL(char * filename); + + virtual int GenerateMesh (Mesh*& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend); + + virtual const Refinement & GetRefinement () const; + }; + + + + class OCCParameters + { + public: + + /// Factor for meshing close edges + double resthcloseedgefac; + + + /// Enable / Disable detection of close edges + int resthcloseedgeenable; + + + + /*! + 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); + + OCCGeometry * LoadOCC_IGES (const char * filename); + OCCGeometry * LoadOCC_STEP (const char * filename); + OCCGeometry * LoadOCC_BREP (const char * filename); + + 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....!!) + extern int OCCGenerateMesh (OCCGeometry & occgeometry, Mesh*& mesh, + MeshingParameters & mparam, + int perfstepsstart, int perfstepsend); + + extern void OCCSetLocalMeshSize(OCCGeometry & geom, Mesh & mesh); + + extern void OCCMeshSurface (OCCGeometry & geom, Mesh & mesh, int perfstepsend); + + extern void OCCFindEdges (OCCGeometry & geom, Mesh & mesh); +} + +#endif + +#endif diff --git a/contrib/Netgen/libsrc/occ/occmeshsurf.cpp b/contrib/Netgen/libsrc/occ/occmeshsurf.cpp new file mode 100644 index 0000000000..a1f60db678 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/occmeshsurf.cpp @@ -0,0 +1,735 @@ +#ifdef OCCGEOMETRY + +#include <mystdlib.h> + +#include <occgeom.hpp> +#include <meshing.hpp> +#include <GeomLProp_SLProps.hxx> +#include <ShapeAnalysis_Surface.hxx> + + +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); + + if (!geometry.FastProject (surfi, hnewp, u, v)) + { + // cout << "Fast projection to surface fails! Using OCC projection" << endl; + 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 diff --git a/contrib/Netgen/libsrc/occ/occmeshsurf.hpp b/contrib/Netgen/libsrc/occ/occmeshsurf.hpp new file mode 100644 index 0000000000..198ade67ce --- /dev/null +++ b/contrib/Netgen/libsrc/occ/occmeshsurf.hpp @@ -0,0 +1,203 @@ +#ifdef OCCGEOMETRY + +#ifndef FILE_OCCMESHSURF +#define FILE_OCCMESHSURF + +#include "occgeom.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 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; + + 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 void ProjectToSurface (Point<3> & p, int surfi) const; + + virtual void ProjectToSurface (Point<3> & p, int surfi, PointGeomInfo & gi) const; +}; + + + +#endif + + + +#endif diff --git a/contrib/Netgen/libsrc/occ/occpkg.cpp b/contrib/Netgen/libsrc/occ/occpkg.cpp new file mode 100644 index 0000000000..aeb691e595 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/occpkg.cpp @@ -0,0 +1,1020 @@ +#ifdef OCCGEOMETRY + +#include <mystdlib.h> +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <occgeom.hpp> + + +#include <incvis.hpp> +#include <visual.hpp> + +#include "../meshing/bcfunctions.hpp" + +#include "vsocc.hpp" + + +extern "C" int Ng_occ_Init (Tcl_Interp * interp); + + + +namespace netgen +{ + extern NetgenGeometry * ng_geometry; + extern AutoPtr<Mesh> 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)); + } + }; + + + + + int Ng_SetOCCVisParameters (ClientData clientData, + Tcl_Interp * interp, + int argc, tcl_const char *argv[]) + { +#ifdef OCCGEOMETRY + int showvolume; + OCCGeometry * occgeometry = dynamic_cast<OCCGeometry*> (ng_geometry); + + 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<OCCGeometry*> (ng_geometry); + + 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<OCCGeometry*> (ng_geometry); + + 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<TopoDS_Shape&> (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<OCCGeometry*> (ng_geometry); + 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.Ptr()) + { + 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<Vec3d> 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<Vec3d> face_colours; + GetFaceColours(*mesh,face_colours); + + int colourind = atoi (argv[2]); + + for(int i = 1; i <= mesh->GetNFD(); i++) + { + Array<SurfaceElementIndex> 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<Vec3d> face_colours; + GetFaceColours(*mesh,face_colours); + + int colourind = atoi (argv[2]); + + for(int i = 1; i <= mesh->GetNFD(); i++) + { + Array<SurfaceElementIndex> 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<Vec3d> face_colours; + GetFaceColours(*mesh,face_colours); + + int colourind = atoi (argv[2]); + + for(int i = 1; i <= mesh->GetNFD(); i++) + { + Array<SurfaceElementIndex> 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<Vec3d> face_colours; + GetFaceColours(*mesh,face_colours); + + int colourind = atoi (argv[2]); + + for(int i = 1; i <= mesh->GetNFD(); i++) + { + Array<SurfaceElementIndex> 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.Ptr()) + { + 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<OCCGeometry*> (ng_geometry); + 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 + diff --git a/contrib/Netgen/libsrc/occ/utilities.h b/contrib/Netgen/libsrc/occ/utilities.h new file mode 100644 index 0000000000..8cb9e3055e --- /dev/null +++ b/contrib/Netgen/libsrc/occ/utilities.h @@ -0,0 +1,112 @@ +// 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 informations if _DEBUG_ is defined --- */ + +#ifndef UTILITIES_H +#define UTILITIES_H + +#include <string> +#include <iostream> +#include <cstdlib> +// #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__<<"] : "<<msg<<endl);} +#define PYSCRIPT(msg) {SLog->putMessage(*SLog<<"---PYSCRIPT--- "<<msg<<endl);} + +/* --- To print date and time of compilation of current source --- */ + +#if defined ( __GNUC__ ) +#define COMPILER "g++" +#elif defined ( __sun ) +#define COMPILER "CC" +#elif defined ( __KCC ) +#define COMPILER "KCC" +#elif defined ( __PGI ) +#define COMPILER "pgCC" +#elif defined ( __alpha ) +#define COMPILER "cxx" +#else +#define COMPILER "undefined" +#endif + +#ifdef INFOS_COMPILATION +#error INFOS_COMPILATION already defined +#endif + +#define INFOS_COMPILATION { \ + SLog->putMessage(\ + *SLog<<__FILE__<<" ["<< __LINE__<<"] : "\ + << "COMPILED with " << COMPILER \ + << ", " << __DATE__ \ + << " at " << __TIME__ <<endl); } + +#ifdef _DEBUG_ + +/* --- the following MACROS are useful at debug time --- */ + +#define MYTRACE *SLog << "- Trace " << __FILE__ << " [" << __LINE__ << "] : " + +#define MESSAGE(msg) {SLog->putMessage( MYTRACE <<msg<<endl<<ends); } +#define SCRUTE(var) {SLog->putMessage( MYTRACE << #var << "=" << var <<endl<<ends); } + +#define REPERE *SLog << " --------------" << endl +#define BEGIN_OF(msg) {REPERE;MYTRACE<<"Begin of: " <<msg<<endl;REPERE;} +#define END_OF(msg) {REPERE;MYTRACE<<"Normal end of: "<<msg<<endl;REPERE;} + +#define HERE {cout<<flush ;cerr<<"- Trace "<<__FILE__<<" ["<<__LINE__<<"] : "<<flush ;} + +#define INTERRUPTION(code) {HERE;cerr<<"INTERRUPTION return code= "<<code<< endl;std::exit(code);} + +#ifndef ASSERT +#define ASSERT(condition) \ + if (!(condition)){HERE;cerr<<"CONDITION "<<#condition<<" NOT VERIFIED"<<endl;INTERRUPTION(1);} +#endif /* ASSERT */ + + +#else /* ifdef _DEBUG_*/ + +#define HERE +#define SCRUTE(var) {} +#define MESSAGE(msg) {} +#define REPERE +#define BEGIN_OF(msg) {} +#define END_OF(msg) {} + +#define INTERRUPTION(code) {} + +#ifndef ASSERT +#define ASSERT(condition) {} +#endif /* ASSERT */ + + +#endif /* ifdef _DEBUG_*/ + +#endif /* ifndef UTILITIES_H */ diff --git a/contrib/Netgen/libsrc/occ/vsocc.cpp b/contrib/Netgen/libsrc/occ/vsocc.cpp new file mode 100644 index 0000000000..64a07dffc6 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/vsocc.cpp @@ -0,0 +1,764 @@ +#ifndef NOTCL + +#ifdef OCCGEOMETRY + +#include <mystdlib.h> +#include <myadt.hpp> +#include <meshing.hpp> + +#include <occgeom.hpp> + +#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 <visual.hpp> + +#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(); + 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 diff --git a/contrib/Netgen/libsrc/occ/vsocc.hpp b/contrib/Netgen/libsrc/occ/vsocc.hpp new file mode 100644 index 0000000000..3021fe7c70 --- /dev/null +++ b/contrib/Netgen/libsrc/occ/vsocc.hpp @@ -0,0 +1,33 @@ +#ifndef FILE_VSOCC +#define FILE_VSOCC + +/**************************************************************************/ +/* File: vsocc.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 05. Jan. 2011 */ +/**************************************************************************/ + +namespace netgen +{ + + class VisualSceneOCCGeometry : public VisualScene + { + Array<int> trilists; + Array<int> 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 diff --git a/contrib/Netgen/libsrc/stlgeom/Makefile.am b/contrib/Netgen/libsrc/stlgeom/Makefile.am new file mode 100644 index 0000000000..c8ea07aaa5 --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/Makefile.am @@ -0,0 +1,15 @@ +noinst_HEADERS = meshstlsurface.hpp stlgeom.hpp stlline.hpp \ +stltool.hpp stltopology.hpp vsstl.hpp + +AM_CPPFLAGS = -I$(top_srcdir)/libsrc/include $(TCL_INCLUDES) +METASOURCES = AUTO + +lib_LTLIBRARIES = libstl.la libstlvis.la + +libstl_la_SOURCES = meshstlsurface.cpp stlgeom.cpp stlgeomchart.cpp \ + stlgeommesh.cpp stlline.cpp stltool.cpp stltopology.cpp + + +libstlvis_la_SOURCES = stlpkg.cpp vsstl.cpp +libstlvis_la_LIBADD = libstl.la $(top_builddir)/libsrc/linalg/libla.la + diff --git a/contrib/Netgen/libsrc/stlgeom/meshstlsurface.cpp b/contrib/Netgen/libsrc/stlgeom/meshstlsurface.cpp new file mode 100644 index 0000000000..fcbb1e021b --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/meshstlsurface.cpp @@ -0,0 +1,1133 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <gprim.hpp> + +#include <meshing.hpp> + + +#include "stlgeom.hpp" + + +namespace netgen +{ + +static void STLFindEdges (STLGeometry & geom, + class Mesh & mesh) +{ + int i, j; + double h; + + h = mparam.maxh; + + // mark edge points: + //int ngp = geom.GetNP(); + + geom.RestrictLocalH(mesh, h); + + PushStatusF("Mesh Lines"); + + Array<STLLine*> meshlines; + Array<Point3d> meshpoints; + + PrintMessage(3,"Mesh Lines"); + + for (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 + int pim; + for (i = 1; i <= meshpoints.Size(); i++) + { + geom.meshpoints.Append(meshpoints.Get(i)); //testing + + pim = mesh.AddPoint(meshpoints.Get(i)); + } + //(++++++++++++++testing + for (i = 1; i <= geom.GetNLines(); i++) + { + geom.meshlines.Append(meshlines.Get(i)); + } + //++++++++++++++testing) + + PrintMessage(7,"feed with edges"); + + for (i = 1; i <= meshlines.Size(); i++) + { + STLLine* line = meshlines.Get(i); + (*testout) << "store line " << i << endl; + for (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; + seg[1] = p2; + 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; + seg2[1] = p1; + 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); + + + /* + // should be start triangle and end triangle + int bothtrigs1[2] = { trig1, trig1 }; + meshing.AddBoundaryElement (p1, p2, sizeof (bothtrigs1), &bothtrigs1); + + int bothtrigs2[2] = { trig2, trig2 }; + meshing.AddBoundaryElement (p2, p1, sizeof (bothtrigs2), &bothtrigs2); + */ + } + } + + PopStatus(); +} + + + + +void STLSurfaceMeshing1 (STLGeometry & geom, + class Mesh & mesh, + int retrynr); + +int STLSurfaceMeshing (STLGeometry & geom, + class Mesh & mesh) +{ + int i, j; + PrintFnStart("Do Surface Meshing"); + + geom.PrepareSurfaceMeshing(); + + if (mesh.GetNSeg() == 0) + STLFindEdges (geom, mesh); + + int nopen; + int outercnt = 20; + + // mesh.Save ("mesh.edges"); + + for (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 (i = 1; i <= nopen; i++) + { + const Segment & seg = mesh.GetOpenSegment (i); + geom.AddMarkedSeg(mesh.Point(seg[0]),mesh.Point(seg[1])); + } + + geom.InitMarkedTrigs(); + for (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<int> openseght (nopen+1); + for (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<int> newpht(100); + + int nsegold = mesh.GetNSeg(); + for (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 elemetns (intersecting..) + + + + PrintMessage(5,"check overlapping"); + // mesh.FindOpenElements(); // would leed to locked points + if(mesh.CheckOverlappingBoundary()) + { + return MESHING3_BADSURFACEMESH; + } + + + geom.InitMarkedTrigs(); + + for (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<Point3d> refpts; + Array<double> refh; + + // was commented: + + for (i = 1; i <= mesh.GetNSE(); i++) + if (mesh.SurfaceElement(i).BadElement()) + { + for (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 (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 (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) +{ + int i, j; + double h; + + + h = mparam.maxh; + + mesh.FindOpenSegments(); + + Array<int> spiralps(0); + spiralps.SetSize(0); + for (i = 1; i <= geom.GetNP(); i++) + { + if (geom.GetSpiralPoint(i)) {spiralps.Append(i);} + } + + PrintMessage(7,"NO spiralpoints = ", spiralps.Size()); + //int spfound; + int sppointnum; + int spcnt = 0; + + Array<int> meshsp(mesh.GetNP()); + for (i = 1; i <= mesh.GetNP(); i++) + { + meshsp.Elem(i) = 0; + for (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<int> opensegsperface(mesh.GetNFD()); + for (i = 1; i <= mesh.GetNFD(); i++) + opensegsperface.Elem(i) = 0; + for (i = 1; i <= mesh.GetNOpenSegments(); i++) + { + int si = mesh.GetOpenSegment (i).si; + if (si >= 1 && si <= mesh.GetNFD()) + { + opensegsperface.Elem(si)++; + } + else + { + cerr << "illegal face index" << endl; + } + } + + + double starttime = GetTime (); + + for (int fnr = 1; fnr <= mesh.GetNFD(); fnr++) + if (opensegsperface.Get(fnr)) + { + if (multithread.terminate) + return; + + PrintMessage(5,"Meshing surface ", fnr, "/", mesh.GetNFD()); + MeshingSTLSurface meshing (geom, mparam); + + meshing.SetStartTime (starttime); + + for (i = 1; i <= mesh.GetNP(); i++) + { + /* + spfound = 0; + for (j = 1; j <= spiralps.Size(); j++) + { + if (Dist2(geom.GetPoint(spiralps.Get(j)),mesh.Point(i)) < 1e-20) + {spfound = 1; sppointnum = spiralps.Get(j);} + } + */ + sppointnum = 0; + if (i <= meshsp.Size()) + sppointnum = meshsp.Get(i); + + //spfound = 0; + if (sppointnum) + { + MultiPointGeomInfo mgi; + + int ntrigs = geom.NOTrigsPerPoint(sppointnum); + spcnt++; + + for (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); + + } + else + { + meshing.AddPoint (mesh.Point(i), i); + } + } + + + for (i = 1; i <= mesh.GetNOpenSegments(); i++) + { + const Segment & seg = mesh.GetOpenSegment (i); + if (seg.si == fnr) + meshing.AddBoundaryElement (seg[0], seg[1], seg.geominfo[0], seg.geominfo[1]); + } + + + PrintMessage(3,"start meshing, trialcnt = ", retrynr); + + /* + (*testout) << "start meshing with h = " << h << endl; + */ + meshing.GenerateMesh (mesh, mparam, h, fnr); // face index + + extern void Render(); + Render(); + } + + + mesh.CalcSurfacesOfNode(); +} + + + +void STLSurfaceOptimization (STLGeometry & geom, + class Mesh & mesh, + MeshingParameters & meshparam) +{ + PrintFnStart("optimize STL Surface"); + + + MeshOptimizeSTLSurface optmesh(geom); + // + + int i; + /* + for (i = 1; i <= mparam.optsteps2d; i++) + { + EdgeSwapping (mesh, 1, 1); + CombineImprove (mesh, 1); + optmesh.ImproveMesh (mesh, 0, 10, 1, 1); + } + */ + + optmesh.SetFaceIndex (0); + optmesh.SetImproveEdges (0); + optmesh.SetMetricWeight (meshparam.elsizeweight); + + PrintMessage(5,"optimize string = ", meshparam.optimize2d, " elsizew = ", meshparam.elsizeweight); + + for (i = 1; i <= meshparam.optsteps2d; i++) + for (size_t j = 1; j <= strlen(meshparam.optimize2d); 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]; + int i; + + if (gi.GetNPGI() >= 9999) + { + PrintError("In Transform to plane: increase size of trigs!!!"); + } + + for (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) +{ + int i; + + for (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) +{ + Vec3d baselinenormal = geom.meshtrignv; + + int lineendtrig = gi.trignum; + + + return geom.TrigIsInOC (lineendtrig, geom.meshchart); + + // Vec3d linenormal = geom.GetTriangleNormal (lineendtrig); + // return ( (baselinenormal * linenormal) > cos (30 * (M_PI/180)) ); +} + +void MeshingSTLSurface :: +GetChartBoundary (Array<Point2d > & points, + Array<Point3d > & points3d, + Array<INDEX_2> & 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(); + + /* + geometry.GetSurface(surfind)->CalcGradient (p, n); + n /= n.Length(); + if (geometry.GetSurface(surfind)->Inverse()) + n *= -1; + */ +} + + + + + + + + + + +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; +}; + + +} diff --git a/contrib/Netgen/libsrc/stlgeom/meshstlsurface.hpp b/contrib/Netgen/libsrc/stlgeom/meshstlsurface.hpp new file mode 100644 index 0000000000..4e678439b4 --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/meshstlsurface.hpp @@ -0,0 +1,121 @@ +#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<Point2d > & points, + Array<Point3d > & poitns3d, + Array<INDEX_2> & 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; + + 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 void ProjectToSurface (Point<3> & p, int surfi) const; + virtual void ProjectToSurface (Point<3> & p, int surfi, PointGeomInfo & gi) const; +}; + + + +#endif + diff --git a/contrib/Netgen/libsrc/stlgeom/stlgeom.cpp b/contrib/Netgen/libsrc/stlgeom/stlgeom.cpp new file mode 100644 index 0000000000..b0cfe87aa5 --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/stlgeom.cpp @@ -0,0 +1,3506 @@ +#include <meshing.hpp> + +#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); + 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() + */ +{ + edgedata = new STLEdgeDataList(*this); + externaledges.SetSize(0); + Clear(); + meshchart = 0; // initialize all ?? JS + + if (geomsearchtreeon) + searchtree = new Box3dTree (GetBoundingBox().PMin() - Vec3d(1,1,1), + GetBoundingBox().PMax() + Vec3d(1,1,1)); + else + searchtree = NULL; + + status = STL_GOOD; + statustext = "Good Geometry"; + smoothedges = NULL; +} + +STLGeometry :: ~STLGeometry() +{ + delete edgedata; +} + +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 (Mesh*& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend) +{ + return STLMeshingDummy (this, mesh, mparam, perfstepsstart, perfstepsend); +} + + +const Refinement & STLGeometry :: GetRefinement () const +{ + return RefinementSTLGeometry (*this); +} + + + +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; // neigbour 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<INDEX_2> 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<int> 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)); + return edges.Append(e); +} + +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<int> 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<Point<3> > 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<Point<3> >& eps) +{ + int i; + int ne = eps.Size()/2; + + Array<int> epsi; + Box<3> bb = GetBoundingBox(); + bb.Increase(1); + + Point3dTree ptree (bb.PMin(), + bb.PMax()); + Array<int> 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<Point3d> importpoints; + Array<int> importlines; + Array<int> 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<int> 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<int> 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<int>& vic) +{ + if (starttrig == 0 || starttrig > GetNT()) {return;} + + Array<int> 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 <int> list1; + list1.SetSize(0); + Array <int> 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 <int> list1; + list1.SetSize(0); + Array <int> 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() +{ + double ar = 0; + int i; + for (i = 1; i <= GetNT(); i++) + { + ar += GetTriangle(i).Area(points); + } + return ar; +} + +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<STLReadTriangle> & 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<int> 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() +{ + int i, j, k; + + Box<3> geombox = GetBoundingBox(); + Point<3> pmin = geombox.PMin(); + Point<3> pmax = geombox.PMax(); + + Box3dTree setree(pmin, pmax); + Array<int> inters; + + int oltrigs = 0; + markedtrigs.SetSize(GetNT()); + + for (i = 1; i <= GetNT(); i++) + SetMarkedTrig(i, 0); + + for (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); + } + + for (i = 1; i <= GetNT(); i++) + { + const STLTriangle & tri = GetTriangle(i); + + Point<3> tpmin = tri.box.PMin(); + Point<3> tpmax = tri.box.PMax(); + + setree.GetIntersecting (tpmin, tpmax, inters); + + for (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 (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])) + { + oltrigs++; + PrintMessage(5,"Intersecting Triangles: trig ",i," with ",inters.Get(j),"!"); + SetMarkedTrig(i, 1); + SetMarkedTrig(inters.Get(j), 1); + } + } + } + + PrintMessage(3,"Check Geometry Overlapping: overlapping triangles = ",oltrigs); + 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<int> 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<int> 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() +{ + int i; + for (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 i; + + int ecnt = 0; + edgedata->SetSize(GetNT()/2*3); + + for (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() +{ + PrintMessage(5,"calc edge data angles"); + + int i; + + for (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 (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); + */ + } + +} + +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;} + + int i; + for (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 (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 (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 + int i; + for (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<int> edgecnt; + Array<int> chartindex; + edgecnt.SetSize(GetNOFaces()); + chartindex.SetSize(GetNOFaces()); + + int i,j; + for (i = 1; i <= GetNOFaces(); i++) + { + edgecnt.Elem(i) = 0; + chartindex.Elem(i) = 0; + } + + for (i = 1; i <= GetNT(); i++) + { + int fn = GetTriangle(i).GetFaceNum(); + if (!chartindex.Get(fn)) {chartindex.Elem(fn) = GetChartNr(i);} + for (j = 1; j <= 3; j++) + { + edgecnt.Elem(fn) += GetNEPP(GetTriangle(i).PNum(j)); + } + } + + for (i = 1; i <= GetNOFaces(); i++) + { + if (!edgecnt.Get(i)) {PrintMessage(5,"Face", i, " has no edge!");} + } + + int changed = 0; + int k, ap1, ap2; + for (i = 1; i <= GetNOFaces(); i++) + { + if (!edgecnt.Get(i)) + { + const STLChart& c = GetChart(chartindex.Get(i)); + for (j = 1; j <= c.GetNChartT(); j++) + { + const STLTriangle& t1 = GetTriangle(c.GetChartTrig(j)); + for (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); + changed = 1; + } + } + } + } + + } + + 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<int> 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<int> 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<int> 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<int> todolist; + Array<int> 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<int> todolist; + Array<int> 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<int> (GetNE()/10 + 1); + + + // Jack: Ok ? + // UseExternalEdges(); + + PushStatusF("Build Smooth Edges"); + + int i, j;//, k, l; + int nt = GetNT(); + Vec3d ng1, ng2; + + for (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 (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<int>& 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<int> trigsaroundp; + Array<int> 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<int>& 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); + } +} +} diff --git a/contrib/Netgen/libsrc/stlgeom/stlgeom.hpp b/contrib/Netgen/libsrc/stlgeom/stlgeom.hpp new file mode 100644 index 0000000000..05c7b014fb --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/stlgeom.hpp @@ -0,0 +1,459 @@ +#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 <meshing.hpp> + + +namespace netgen +{ + extern int IsInArray(int n, const Array<int>& ia); + extern int AddIfNotExists(Array<int>& list, int x); + + extern DLL_HEADER MeshingParameters mparam; + + + +#include "stltopology.hpp" +#include "stltool.hpp" +#include "stlline.hpp" + + + + + + + + class STLEdgeDataList + { + Array<int> 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<twoint>& line); + void BuildClusterWithEdge(int ep1, int ep2, Array<twoint>& line); + + int GetNEPPStat(int p, int status) const; + int GetNConfCandEPP(int p) const; + }; + + + + + + + class STLGeometry : public STLTopology, public NetgenGeometry + { + // edges to be meshed: + Array<STLEdge> edges; + //edges per point + TABLE<int> edgesperpoint; + + // line: a connection of edges + Array<STLLine*> lines; + Array<int> lineendpoints; //per geometrypoint, 1 = is endpoint; 0 = no endpoint, + + Array<Vec3d> normals; //normals belong to points! + + Array<twoint> externaledges; + + int undoexternaledges; + Array<twoint> storedexternaledges; + + STLEdgeDataList * edgedata; + // STLEdgeDataList edgedata_store; + int calcedgedataanglesnew; + + int edgedatastored; + + + + int facecnt; + //meshpoint is only set, if an edge is at this point!!! + + Array<int> vicinity; //is one, if a triangle belongs to vicinity (eg. of selecttrig) + Array<int> markedtrigs; //is one, if a triangle belongs to marked triangles (calcdirtystrigs) + Array<Point3d> markedsegs; //every pointpair is a segment!!! + Array<twoint> selectedmultiedge; + + + //spiralpoints: + Array<int> spiralpoints; + // + Array<STLChart*> atlas; + //marks all already charted trigs with chartnumber + Array<int> chartmark; + //outerchartspertrig, ascending sorted + TABLE<int> outerchartspertrig; + + + //for meshing and project: + Array<int> meshcharttrigs; //per trig: 1=belong to chart, 0 not + int meshchart; + + Array<int> ha_points; // help array, np long, filled with 0 + + + // sharp geometric edges not declared as edges + // (not considered for spiral check) + INDEX_2_HASHTABLE<int> * smoothedges; + + + //transformation: + Vec<3> meshtrignv; + Vec<3> ex, ey, ez; + Point<3> p1; + + 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<STLLine*> meshlines; + Array<Point3d> meshpoints; + + public: + STLGeometry(); + virtual ~STLGeometry(); + + + void Clear(); + + virtual void Save (string filename) const; + + + void STLInfo(double* data); + //stldoctor: + void SmoothNormals(); + void MarkNonSmoothNormals(); + + void CalcEdgeData(); + void CalcEdgeDataAngles(); + + const STLEdgeDataList& EdgeDataList() const {return *edgedata;} + + void UndoEdgeChange(); + void StoreEdgeData(); + void RestoreEdgeData(); + + //void ClearSelectedMultiEdge() {selectedmultiedge.SetSize(0);} + //void AddSelectedMultiEdge(twoint ep) {selectedmultiedge.Append(ep);} + //int SelectedMultiEdgeSize() {return selectedmultiedge.Size();} + const Array<twoint>& SelectedMultiEdge() {return selectedmultiedge;} + twoint GetNearestSelectedDefinedEdge(); + void BuildSelectedMultiEdge(twoint ep); + void BuildSelectedEdge(twoint ep); + void BuildSelectedCluster(twoint ep); + + void ImportEdges(); + void AddEdges(const Array<Point<3> >& eps); + void ExportEdges(); + void LoadEdgeData(const char* file); + void SaveEdgeData(const char* file); + // void SetEdgeAtSelected(int mode); + + + void STLDoctorConfirmEdge(); + void STLDoctorCandidateEdge(); + void STLDoctorExcludeEdge(); + void STLDoctorUndefinedEdge(); + + void STLDoctorSetAllUndefinedEdges(); + void STLDoctorEraseCandidateEdges(); + void STLDoctorConfirmCandidateEdges(); + void STLDoctorConfirmedToCandidateEdges(); + + void STLDoctorDirtyEdgesToCandidates(); + void STLDoctorLongLinesToCandidates(); + + void UndoExternalEdges(); + void StoreExternalEdges(); + void RestoreExternalEdges(); + + void ImportExternalEdges(const char * filename); // Flame edges, JS + // void LoadExternalEdges(); + + void BuildExternalEdgesFromEdges(); + void SaveExternalEdges(); + void AddExternalEdgeAtSelected(); + void AddClosedLinesToExternalEdges(); + void AddLongLinesToExternalEdges(); + void AddAllNotSingleLinesToExternalEdges(); + void STLDoctorBuildEdges(); + void AddExternalEdgesFromGeomLine(); + void DeleteDirtyExternalEdges(); + void DeleteExternalEdgeAtSelected(); + 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);} + + void DestroyDirtyTrigs(); + void CalcNormalsFromGeometry(); + void MoveSelectedPointToMiddle(); + void NeighbourAnglesOfSelectedTrig(); + void PrintSelectInfo(); + void ShowSelectedTrigChartnum(); + void ShowSelectedTrigCoords(); + void SmoothGeometry (); + + + void LoadMarkedTrigs(); + 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;} + void CalcVicinity(int starttrig); + void GetVicinity(int starttrig, int size, Array<int>& vic); + + int Vicinity(int trig) const; + + void InitMarkedTrigs(); + void MarkDirtyTrigs(); + void SmoothDirtyTrigs(); + void GeomSmoothRevertedTrigs(); + void MarkRevertedTrigs(); + double CalcTrigBadness(int i); + int IsMarkedTrig(int trig) const; + void SetMarkedTrig(int trig, int num); + void MarkTopErrorTrigs (); + + //Selected triangle + void SetSelectTrig(int trig); + int GetSelectTrig() const; + void SetNodeOfSelTrig(int n); + int GetNodeOfSelTrig() const; + + + int AddNormal(const Vec3d& n) {return normals.Append(n);} + 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) {return edges.Append(v);} + 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<STLReadTriangle> & 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<int>& outercharttrigs, + Array<int>& chartpointchecked, Array<int>& 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<int>& 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<twoint>& limes, int chartnum); + + //FOR MESHING + int GetMeshChartNr () { return meshchart; } + void GetMeshChartBoundary (Array<Point2d > & points, + Array<Point3d > & points3d, + Array<INDEX_2> & 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) {return lines.Append(line);} + 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(); + + void RestrictLocalH(class Mesh & mesh, double gh); + void RestrictLocalHCurv(class Mesh & mesh, double gh); + void RestrictHChartDistOneChart(int chartnum, Array<int>& acttrigs, class Mesh & mesh, + double gh, double fact, double minh); + + friend class MeshingSTLSurface; + + + virtual int GenerateMesh (Mesh*& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend); + + virtual const Refinement & GetRefinement () const; + }; + + +#include "meshstlsurface.hpp" + + + + extern int STLMeshingDummy (STLGeometry* stlgeometry, Mesh*& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend); + + +} +#endif diff --git a/contrib/Netgen/libsrc/stlgeom/stlgeomchart.cpp b/contrib/Netgen/libsrc/stlgeom/stlgeomchart.cpp new file mode 100644 index 0000000000..105ba8c641 --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/stlgeomchart.cpp @@ -0,0 +1,798 @@ +//20.11.1999 third part of stlgeom.cc, functions with chart and atlas + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <gprim.hpp> + +#include <meshing.hpp> + +#include "stlgeom.hpp" + +namespace netgen +{ + +int chartdebug = 0; + + + +void STLGeometry :: MakeAtlas(Mesh & mesh) +{ + + double h, h2; + + h = mparam.maxh; + + + PushStatusF("Make Atlas"); + + int i,j,k,l; + + double atlasminh = 5e-3 * Dist (boundingbox.PMin(), boundingbox.PMax()); + PrintMessage(5, "atlasminh = ", atlasminh); + + //speedup for make atlas + if (GetNT() > 50000) + { + mesh.SetGlobalH(0.05*Dist (boundingbox.PMin(), boundingbox.PMax())); + } + + + atlas.SetSize(0); + ClearSpiralPoints(); + BuildSmoothEdges(); + + + 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<int> outermark(GetNT()); //marks all trigs form actual outer region + Array<int> outertested(GetNT()); //marks tested trigs for outer region + Array<int> pointstochart(GetNP()); //point in chart becomes chartnum + Array<int> innerpointstochart(GetNP()); //point in chart becomes chartnum + Array<int> chartpoints; //point in chart becomes chartnum + Array<int> innerchartpoints; + Array<int> dirtycharttrigs; + Array<int> chartpointchecked; + + Array<int> chartdistacttrigs; //outercharttrigs + chartdistacttrigs.SetSize(GetNT()); + for (i = 1; i <= GetNT(); i++) + { + chartdistacttrigs.Elem(i) = 0; + } + + STLBoundary chartbound(this); //knows the actual chart boundary + //int chartboundarydivisions = 10; + markedsegs.SetSize(0); //for testing!!! + + chartpointchecked.SetSize(GetNP()); //for dirty-chart-trigs + + outermark.SetSize(GetNT()); + outertested.SetSize(GetNT()); + pointstochart.SetSize(GetNP()); + innerpointstochart.SetSize(GetNP()); + chartmark.SetSize(GetNT()); + + for (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+++++++++++++++"); } + + for (i = 1; i <= GetNT(); i++) + { + chartmark.Elem(i) = 0; + } + + for (i = 1; i <= GetNT(); i++) + { + outermark.Elem(i) = 0; + outertested.Elem(i) = 0; + } + + int markedtrigcnt = 0; + int found = 1; + double atlasarea = Area(); + double workedarea = 0; + double showinc = 100.*5000./(double)GetNT(); + double nextshow = 0; + Point<3> startp; + int lastunmarked = 1; + int prelastunmarked; + + PrintMessage(5,"one dot per 5000 triangles: "); + + while(markedtrigcnt < GetNT() && found) + { + if (multithread.terminate) + {PopStatus();return;} + + if (workedarea / atlasarea*100. >= nextshow) + {PrintDot(); nextshow+=showinc;} + + SetThreadPercent(100.0 * workedarea / atlasarea); + + /* + for (j = 1; j <= GetNT(); j++) + { + outermark.Elem(j) = 0; + } + */ + STLChart * chart = new STLChart(this); + atlas.Append(chart); + + //find unmarked trig + prelastunmarked = lastunmarked; + j = lastunmarked; + found = 0; + while (!found && j <= GetNT()) + { + if (!GetMarker(j)) {found = 1; lastunmarked = j;} + else {j++;} + } + + chartpoints.SetSize(0); + innerchartpoints.SetSize(0); + chartbound.Clear(); + chartbound.SetChart(chart); + + if (!found) {PrintSysError("Make Atlas, no starttrig found"); return;} + + //find surrounding trigs + int starttrig = j; + + double tdist; + startp = GetPoint(GetTriangle(starttrig).PNum(1)); + + int accepted; + int chartnum = GetNOCharts(); + + Vec<3> sn = GetTriangle(starttrig).Normal(); + chart->SetNormal (startp, sn); + + + SetMarker(starttrig, chartnum); + markedtrigcnt++; + chart->AddChartTrig(starttrig); + chartbound.AddTriangle(GetTriangle(starttrig)); + + workedarea += GetTriangle(starttrig).Area(points); + + for (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)); + } + + Vec<3> n2, n3; + int changed = 1; + int nt; + int ic; + int oldstartic = 1; + int oldstartic2; + int np1, np2; + + while (changed) + { + changed = 0; + oldstartic2 = oldstartic; + oldstartic = chart->GetNT(); + // for (ic = oldstartic2; ic <= chart->GetNT(); ic++) + for (ic = oldstartic2; ic <= oldstartic; ic++) + { + i = chart->GetTrig(ic); + if (GetMarker(i) == chartnum) + { + for (j = 1; j <= NONeighbourTrigs(i); j++) + { + nt = NeighbourTrig(i,j); + GetTriangle(i).GetNeighbourPoints(GetTriangle(nt),np1,np2); + if (GetMarker(nt) == 0 && !IsEdge(np1,np2)) + { + n2 = GetTriangle(nt).Normal(); + if ( (n2 * sn) >= coschartangle ) + { + + 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; + } + } + } + + } + } + */ + + int nnp1, nnp2; + int nnt; + //find overlapping charts exacter: + for (k = 1; k <= 3; k++) + { + nnt = NeighbourTrig(nt,k); + if (GetMarker(nnt) != chartnum) + { + GetTriangle(nt).GetNeighbourPoints(GetTriangle(nnt),nnp1,nnp2); + + accepted = chartbound.TestSeg(GetPoint(nnp1), + GetPoint(nnp2), + sn,sinchartangle,1 /*chartboundarydivisions*/ ,points, eps); + + + n3 = GetTriangle(nnt).Normal(); + if ( (n3 * sn) >= coschartangle && + IsSmoothEdge (nnp1, nnp2) ) + accepted = 1; + } + if (!accepted) {break;} + } + + /* + mindist = 1E50; + for (int ii = 1; ii <= 3; ii++) + { + tdist = Dist(GetPoint(GetTriangle(nt).PNum(ii)),startp); + if (tdist < mindist) {mindist = tdist;} + } + if (mindist > maxdist1) {accepted = 0;} + */ + + if (accepted) + { + SetMarker(nt, chartnum); + changed = 1; + markedtrigcnt++; + workedarea += GetTriangle(nt).Area(points); + chart->AddChartTrig(nt); + + chartbound.AddTriangle(GetTriangle(nt)); + + for (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)); + } + } + } + } + } + } + } + } + } + + + //find outertrigs + + // chartbound.Clear(); + // warum, ic-bound auf edge macht Probleme js ??? + + + outermark.Elem(starttrig) = chartnum; + //chart->AddOuterTrig(starttrig); + changed = 1; + oldstartic = 1; + while (changed) + { + changed = 0; + oldstartic2 = oldstartic; + oldstartic = chart->GetNT(); + //for (ic = oldstartic2; ic <= chart->GetNT(); ic++) + for (ic = oldstartic2; ic <= oldstartic; ic++) + { + i = chart->GetTrig(ic); + + if (outermark.Get(i) == chartnum) + { + for (j = 1; j <= NONeighbourTrigs(i); j++) + { + nt = NeighbourTrig(i,j); + if (outermark.Get(nt) == chartnum) + continue; + + const STLTriangle & ntrig = GetTriangle(nt); + GetTriangle(i).GetNeighbourPoints(GetTriangle(nt),np1,np2); + + if (IsEdge (np1, np2)) + continue; + + + /* + if (outertested.Get(nt) == chartnum) + continue; + */ + outertested.Elem(nt) = chartnum; + + + n2 = GetTriangle(nt).Normal(); + /* + double ang; + ang = Angle(n2,sn); + if (ang < -M_PI*0.5) {ang += 2*M_PI;} + + (*testout) << "ang < ocharang = " << (fabs(ang) <= outerchartangle); + (*testout) << " = " << ( (n2 * sn) >= cosouterchartangle) << endl; + + // if (fabs(ang) <= outerchartangle) + */ + //abfragen, ob noch im tolerierten Winkel + if ( (n2 * sn) >= cosouterchartangle ) + { + accepted = 1; + + int isdirtytrig = 0; + Vec<3> gn = GetTriangle(nt).GeomNormal(points); + double gnlen = gn.Length(); + + if (n2 * gn <= cosouterchartanglehalf * gnlen) + {isdirtytrig = 1;} + + //zurueckweisen, falls eine Spiralartige outerchart entsteht + int nnp1, nnp2; + int nnt; + //find overlapping charts exacter: + //do not check dirty trigs! + + + if (spiralcheckon && !isdirtytrig) + for (k = 1; k <= 3; k++) + { + nnt = NeighbourTrig(nt,k); + + if (outermark.Elem(nnt) != chartnum) + { + GetTriangle(nt).GetNeighbourPoints(GetTriangle(nnt),nnp1,nnp2); + + accepted = + chartbound.TestSeg(GetPoint(nnp1),GetPoint(nnp2), + sn,sinouterchartangle, 0 /*chartboundarydivisions*/ ,points, eps); + + + n3 = GetTriangle(nnt).Normal(); + if ( (n3 * sn) >= cosouterchartangle && + IsSmoothEdge (nnp1, nnp2) ) + accepted = 1; + } + if (!accepted) {break;} + } + + //} + + + // outer chart is only small environment of + // inner chart: + if (accepted) + { + accepted = 0; + + for (k = 1; k <= 3; k++) + { + if (innerpointstochart.Get(ntrig.PNum(k)) == chartnum) + { + accepted = 1; + break; + } + } + + if (!accepted) + for (k = 1; k <= 3; k++) + { + Point<3> pt = GetPoint(ntrig.PNum(k)); + h2 = sqr(mesh.GetH(pt)); + + for (l = 1; l <= innerchartpoints.Size(); l++) + { + tdist = Dist2(pt, GetPoint (innerchartpoints.Get(l))); + if (tdist < 4 * h2) + { + accepted = 1; + break; + } + } + if (accepted) {break;} + } + } + + + if (accepted) + { + changed = 1; + outermark.Elem(nt) = chartnum; + + if (GetMarker(nt) != chartnum) + { + chartbound.AddTriangle(GetTriangle(nt)); + chart->AddOuterTrig(nt); + for (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)); + } + } + } + } + } + } + } + } + } + //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 (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; + } + + //calculate an estimate meshsize, not to produce to large outercharts, with factor 2 larger! + RestrictHChartDistOneChart(chartnum, chartdistacttrigs, mesh, h, 0.5, atlasminh); + } + + PrintMessage(5,""); + PrintMessage(5,"NO charts=", atlas.Size()); + + int cnttrias = 0; + //int found2; + outerchartspertrig.SetSize(GetNT()); + + for (i = 1; i <= atlas.Size(); i++) + { + //found2 = 1; + for (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 (i = 1; i <= GetNT(); i++) + { + int swap; + for (k = 1; k < GetNOCPT(i); k++) + { + + for (j = 1; j < GetNOCPT(i); j++) + { + 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<int>& 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<twoint>& 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<int>& outercharttrigs, + Array<int>& chartpointchecked, + Array<int>& 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<int> 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)) + { + dirtytrigs.Append(j); + cnt++; + break; //only once per triangle + } + } + } + } + +} + +} diff --git a/contrib/Netgen/libsrc/stlgeom/stlgeommesh.cpp b/contrib/Netgen/libsrc/stlgeom/stlgeommesh.cpp new file mode 100644 index 0000000000..c20c6acfc3 --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/stlgeommesh.cpp @@ -0,0 +1,1590 @@ +//20.11.1999 second part of stlgeom.cc, mainly mesh functions + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <gprim.hpp> + +#include <meshing.hpp> + +#include "stlgeom.hpp" + +namespace netgen +{ +int EdgeUsed(int p1, int p2, Array<INDEX_2>& edges, INDEX_2_HASHTABLE<int>& 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<Point3d> edgepoints; + TABLE<double> edgepointdists; + TABLE<int> edgepointorigines; + TABLE<int> edgepointoriginps; + + Array<int> edgetrigs; + Array<INDEX_2> edgepointnums; + Array<int> edgetriglocinds; + + int size = 3*GetNT(); + INDEX_2_HASHTABLE<int> 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<int> edgelist1; + Array<int> 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<Point3d> 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()); + int i; + for (i = 1; i <= GetNT(); i++) + {meshcharttrigs.Elem(i) = 0;} +} + +void STLGeometry::GetMeshChartBoundary (Array<Point2d > & apoints, + Array<Point3d > & points3d, + Array<INDEX_2> & alines, double h) +{ + int i, j; + twoint seg, newseg; + int zone; + Point<2> p2; + + const STLChart& chart = GetChart(meshchart); + + + for (i = 1; i <= chart.GetNOLimit(); i++) + { + seg = chart.GetOLimit(i); + INDEX_2 i2; + for (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 (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<int> 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<int> trigsinbox; + + if (!geomsearchtreeon) + { + //alter chart-tree + Box<3> box(locpoint, locpoint); + box.Increase (range); + chart.GetTrianglesInBox (box.PMin(), box.PMax(), trigsinbox); + } + else + { + Array<int> 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<double> 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<double> 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..."); + Box3dTree* lsearchtree = new Box3dTree (GetBoundingBox().PMin() - Vec3d(1,1,1), + GetBoundingBox().PMax() + Vec3d(1,1,1)); + + Array<Point3d> pmins(GetNLines()); + Array<Point3d> 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<int> 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<int> acttrigs; //outercharttrigs + acttrigs.SetSize(GetNT()); + for (i = 1; i <= GetNT(); i++) + { + acttrigs.Elem(i) = 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(); + } + + 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<int>& acttrigs, + class Mesh & mesh, double gh, double fact, double minh) +{ + int i = chartnum; + int j; + + double limessafety = stlparam.resthchartdistfac*fact; // original: 2 + double localh; + + double f1,f2; + // mincalch = 1E10; + //maxcalch = -1E10; + Array<int> limes1; + Array<int> limes2; + + Array<Point3d> plimes1; + Array<Point3d> plimes2; + + Array<int> plimes1trigs; //check from wich trig the points come + Array<int> plimes2trigs; + + Array<int> plimes1origin; //either the original pointnumber or zero, if new point + + int divisions = 10; + + int k, t, nt, 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(i); + chart.ClearOLimit(); + chart.ClearILimit(); + + for (j = 1; j <= chart.GetNChartT(); j++) + { + t = chart.GetChartTrig(j); + tt = GetTriangle(t); + for (k = 1; k <= 3; k++) + { + nt = NeighbourTrig(t,k); + if (GetChartNr(nt) != i) + { + tt.GetNeighbourPoints(GetTriangle(nt),np1,np2); + if (!IsEdge(np1,np2) && !GetSpiralPoint(np1) && !GetSpiralPoint(np2)) + { + p3p1 = GetPoint(np1); + p3p2 = GetPoint(np2); + if (AddIfNotExists(limes1,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++) + { + f1 = (double)di/(double)(divisions+1.); + 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); + } + } + } + } + } + + + for (j = 1; j <= chart.GetNT(); j++) + { + acttrigs.Elem(chart.GetTrig(j)) = i; + } + + for (j = 1; j <= chart.GetNOuterT(); j++) + { + t = chart.GetOuterTrig(j); + tt = GetTriangle(t); + for (k = 1; k <= 3; k++) + { + nt = NeighbourTrig(t,k); + + if (acttrigs.Get(nt) != i) + { + tt.GetNeighbourPoints(GetTriangle(nt),np1,np2); + + if (!IsEdge(np1,np2)) + { + p3p1 = GetPoint(np1); + p3p2 = GetPoint(np2); + + if (AddIfNotExists(limes2,np1)) {plimes2.Append(p3p1); plimes2trigs.Append(t);} + if (AddIfNotExists(limes2,np2)) {plimes2.Append(p3p2); plimes2trigs.Append(t);} + chart.AddOLimit(twoint(np1,np2)); + + for (int di = 1; di <= divisions; di++) + { + f1 = (double)di/(double)(divisions+1.); + 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); + } + } + } + } + } + + + double chartmindist = 1E50; + + if (plimes2.Size()) + { + Box3d bbox; + bbox.SetPoint (plimes2.Get(1)); + for (j = 2; j <= plimes2.Size(); j++) + bbox.AddPoint (plimes2.Get(j)); + Point3dTree stree(bbox.PMin(), bbox.PMax()); + for (j = 1; j <= plimes2.Size(); j++) + stree.Insert (plimes2.Get(j), j); + Array<int> foundpts; + + for (j = 1; j <= plimes1.Size(); j++) + { + double mindist = 1E50; + double dist; + + 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++) + { + k = foundpts.Get(kk); + 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;} + } + } + } + +} + + +int STLMeshingDummy (STLGeometry* stlgeometry, Mesh*& mesh, MeshingParameters & mparam, + int perfstepsstart, int perfstepsend) +{ + if (perfstepsstart > perfstepsend) return 0; + + multithread.terminate = 0; + int success = 1; + //int trialcntouter = 0; + + if (perfstepsstart <= MESHCONST_MESHEDGES) + { + + mesh = new Mesh(); + 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 (perfstepsstart <= MESHCONST_MESHSURFACE && + 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 (perfstepsstart <= MESHCONST_OPTSURFACE && + 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 + + extern void Render(); + Render(); + } + stlgeometry->surfaceoptimized = 1; + } + if (multithread.terminate) + return 0; + + if (perfstepsstart <= MESHCONST_MESHVOLUME && + 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 (perfstepsstart <= MESHCONST_OPTVOLUME && + 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 + + extern void Render(); + Render(); + } + } + + + return 0; +} + + + +} diff --git a/contrib/Netgen/libsrc/stlgeom/stlline.cpp b/contrib/Netgen/libsrc/stlgeom/stlline.cpp new file mode 100644 index 0000000000..15226edaf8 --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/stlline.cpp @@ -0,0 +1,780 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <gprim.hpp> + +#include <meshing.hpp> + +#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<twoint>& 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<twoint>& 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<twoint>& 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<twoint>& 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<Point<3> >& ap, int nr) const +{ + return Dist(ap.Get(PNum(nr)),ap.Get(PNum(nr+1))); +} + +double STLLine :: GetLength(const Array<Point<3> >& 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<Point<3> > & 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<Point<3> >& 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<Point<3> >& ap, + Array<Point3d>& mp, double ghi, + class Mesh& mesh) const +{ + 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; + + int i, j; + + Box<3> bbox; + GetBoundingBox (ap, bbox); + double diam = bbox.Diam(); + + double minh = mesh.LocalHFunction().GetMinH (bbox.PMin(), bbox.PMax()); + + double maxseglen = 0; + for (i = 1; i <= GetNS(); i++) + maxseglen = max2 (maxseglen, GetSegLen (ap, i)); + + int nph = 10+int(maxseglen / minh); //anzahl der integralauswertungen pro segment + + Array<double> inthi(GetNS()*nph); + Array<double> curvelen(GetNS()*nph); + + + for (i = 1; i <= GetNS(); i++) + { + //double seglen = GetSegLen(ap,i); + for (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; + 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); + + inthl = 0; //restart each meshseg + for (i = 1; i <= inthlint; i++) + { + while (inthl < 1.000000001 && j <= inthi.Size()) + // while (inthl-1. < 1e-9) && j <= inthi.Size()) + { + inthl += inthi.Get(j)/fact; + dist += curvelen.Get(j); + j++; + } + + //went to 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++; + } + + 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; + */ + return line; +} +} diff --git a/contrib/Netgen/libsrc/stlgeom/stlline.hpp b/contrib/Netgen/libsrc/stlgeom/stlline.hpp new file mode 100644 index 0000000000..06ce585709 --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/stlline.hpp @@ -0,0 +1,188 @@ +#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<int> hashtab; + Array<STLEdgeData> edgedata; + TABLE<int> 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<twoint>& 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<int> pts; + Array<int> lefttrigs; + Array<int> righttrigs; + Array<double> 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<Point<3> >& 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<Point<3> > & 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<Point<3> >& 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<Point<3> >& ap, double dist, int& index) const; + + //return a meshed polyline + STLLine* Mesh(const Array<Point<3> >& ap, + Array<Point3d>& mp, double ghi, + class Mesh& mesh) const; + + void DoSplit() {split = 1;} + int ShouldSplit() const {return split;} +}; + +#endif diff --git a/contrib/Netgen/libsrc/stlgeom/stlpkg.cpp b/contrib/Netgen/libsrc/stlgeom/stlpkg.cpp new file mode 100644 index 0000000000..4282633a4c --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/stlpkg.cpp @@ -0,0 +1,622 @@ +#include <mystdlib.h> +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> + +#include <meshing.hpp> + + +#include <incvis.hpp> +#include <visual.hpp> + +#include <stlgeom.hpp> + +#include "vsstl.hpp" + +extern "C" int Ng_STL_Init (Tcl_Interp * interp); + + + +namespace netgen +{ + extern NetgenGeometry * ng_geometry; + extern AutoPtr<Mesh> mesh; + + static VisualSceneSTLGeometry vsstlgeom; + static VisualSceneSTLMeshing vsstlmeshing; + + char * err_needsstlgeometry = (char*) "This operation needs an STL geometry"; + + + + + + class STLGeometryRegister : public GeometryRegister + { + public: + virtual NetgenGeometry * Load (string filename) const; + 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[]) + { + STLGeometryRegister 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<STLGeometry*> (ng_geometry); + + + 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; + } + + + + + + + + + + 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; + } + + + + + + + + + + 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<STLGeometry*> (ng_geometry); + + 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<STLGeometry*> (ng_geometry); + if (mesh.Ptr() && 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 * STLGeometryRegister :: GetVisualScene (const NetgenGeometry * geom) const + { + STLGeometry * geometry = dynamic_cast<STLGeometry*> (ng_geometry); + if (geometry) + { + vsstlmeshing.SetGeometry (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 STLGeometryRegister); + + 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; +} diff --git a/contrib/Netgen/libsrc/stlgeom/stltool.cpp b/contrib/Netgen/libsrc/stlgeom/stltool.cpp new file mode 100644 index 0000000000..ee06157b08 --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/stltool.cpp @@ -0,0 +1,1287 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <gprim.hpp> + +#include <meshing.hpp> + +#include "stlgeom.hpp" + +namespace netgen +{ + + +//add a point into a pointlist, return pointnumber +int AddPointIfNotExists(Array<Point3d>& ap, const Point3d& p, double eps) +{ + int i; + for (i = 1; i <= ap.Size(); i++) + { + if (Dist(ap.Get(i),p) <= eps ) {return i;} + } + return ap.Append(p); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +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]; + int j; + for (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); + + int j; + for (j = 0; j < ilen; j++) + { + ios << buf[j]; + } +} + +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[j]); + } + 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[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); + + int j; + for (j = 0; j < ilen; j++) + { + ios << buf[j]; + } +} + +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]; + } +} + + +/* +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!!! + int i, j; + for(i = 0; i <= 2; i++) + { + for(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!!! + int i, j; + for(i = 0; i <= 2; i++) + { + for(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 +{ + int i, j; + for(i = 1; i <= 3; i++) + { + for(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 +{ + int i, j; + for(i = 1; i <= 3; i++) + { + for(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<Point<3> >& 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<Point<3> >& 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<Point<3> >& 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<Point<3> >& 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<Point<3> >& 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<Point<3> >& 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<Point<3> >& 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<Point<3> > & 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<Point<3> >& 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<int> (0,0); + outertrigs = new Array<int> (0,0); + ilimit = new Array<twoint> (0,0); + olimit = new Array<twoint> (0,0); + + geometry = ageometry; + + if ( (stlparam.usesearchtree == 1)) + searchtree = new Box3dTree (geometry->GetBoundingBox().PMin() - Vec3d(1,1,1), + geometry->GetBoundingBox().PMax() + Vec3d(1,1,1)); + else + searchtree = NULL; +} + +void STLChart :: AddChartTrig(int i) +{ + charttrigs->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);} +} + +void STLChart :: AddOuterTrig(int i) +{ + 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 +{ + int i; + for (i = 1; i <= charttrigs->Size(); i++) + { + if (charttrigs->Get(i) == nr) {return 1;} + } + for (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<int> & trias) const +{ + if (geomsearchtreeon) {PrintMessage(5,"geomsearchtreeon is set!!!");} + + if (searchtree) + searchtree -> GetIntersecting (pmin, pmax, trias); + else + { + int i; + Box3d box1(pmin, pmax); + box1.Increase (1e-4); + Box3d box2; + + trias.SetSize(0); + + int nt = GetNT(); + for (i = 1; i <= nt; i++) + { + + int trignum = GetTrig(i); + const STLTriangle & trig = geometry->GetTriangle(trignum); + box2.SetPoint (geometry->GetPoint (trig.PNum(1))); + box2.AddPoint (geometry->GetPoint (trig.PNum(2))); + box2.AddPoint (geometry->GetPoint (trig.PNum(3))); + + if (box1.Intersect (box2)) + { + trias.Append (trignum); + } + } + } +} + +//trigs may contain the same triangle double +void STLChart :: MoveToOuterChart(const Array<int>& trigs) +{ + if (!trigs.Size()) {return;} + int i; + for (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<int>& trigs) +{ + if (!trigs.Size()) {return;} + + int i; + for (i = 1; i <= trigs.Size(); i++) + { + charttrigs->Elem(trigs.Get(i)) = -1; + } + + int cnt = 0; + for (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); + } + } + 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 Box3dTree (geometry->GetBoundingBox().PMin() - Vec3d(1,1,1), + geometry->GetBoundingBox().PMax() + Vec3d(1,1,1)); + + for (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<Point<3> > & 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) + : // boundary(), + geometry(ageometry) +{ + ; +} + + +void STLBoundary :: AddOrDelSegment(const STLBoundarySeg & seg) +{ + int i; + int found = 0; + for (i = 1; i <= boundary.Size(); i++) + { + if (found) {boundary.Elem(i-1) = boundary.Get(i);} + if (boundary.Get(i) == seg) {found = 1;} + } + if (!found) + { + boundary.Append(seg); + } + else + { + boundary.SetSize(boundary.Size()-1); + } +} + +void STLBoundary ::AddTriangle(const STLTriangle & t) +{ + 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);} + if (!found2) {seg2.Swap(); boundary.Append(seg2);} + if (!found3) {seg3.Swap(); boundary.Append(seg3);} +} + +int STLBoundary :: TestSeg(const Point<3>& p1, const Point<3> & p2, const Vec<3> & sn, + double sinchartangle, int divisions, Array<Point<3> >& points, double eps) +{ + + if (usechartnormal) + return TestSegChartNV (p1, p2, sn); + + // for statistics + { + int i; + static Array<int> 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; + } + */ + } + } + + + 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) + + 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); +} + + + +// checks, whether 2d projection intersects +int STLBoundary :: TestSegChartNV(const Point3d & p1, const Point3d& p2, + const Vec3d& sn) +{ + int j; + int nseg = NOSegments(); + + Point<2> p2d1 = chart->Project2d (p1); + Point<2> p2d2 = chart->Project2d (p2); + + Box<2> box2d; + box2d.Set (p2d1); + box2d.Add (p2d2); + /* + Point2d pmin(p2d1); + pmin.SetToMin (p2d2); + Point2d pmax(p2d1); + pmax.SetToMax (p2d2); + */ + + Line2d l1 (p2d1, p2d2); + + double lam1, lam2; + double eps = 1e-3; + + for (j = 1; j <= nseg; j++) + { + const STLBoundarySeg & seg = GetSegment(j); + + if (!box2d.Intersect (seg.BoundingBox())) + continue; + /* + if (seg.P2DMin()(0) > pmax(0)) continue; + if (seg.P2DMin()(1) > pmax(1)) continue; + if (seg.P2DMax()(0) < pmin(0)) continue; + if (seg.P2DMax()(1) < pmin(1)) continue; + */ + + if (seg.IsSmoothEdge()) continue; + + const Point<2> & sp1 = seg.P2D1(); + const Point<2> & sp2 = seg.P2D2(); + + + Line2d l2 (sp1, sp2); + + int err = + CrossPointBarycentric (l1, l2, lam1, lam2); + /* + if (chartdebug) + { + + (*testout) << "lam1 = " << lam1 << ", lam2 = " << lam2 << endl; + (*testout) << "p2d = " << p2d1 << ", " << p2d2 << endl; + (*testout) << "sp2d = " << sp1 << ", " << sp2 << endl; + (*testout) << "i1,2 = " << seg.I1() << ", " << seg.I2() << endl; + + } + */ + if (!err && lam1 > eps && lam1 < 1-eps && + lam2 > eps && lam2 < 1-eps) + return 0; + } + return 1; +} + + + +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; + + +} diff --git a/contrib/Netgen/libsrc/stlgeom/stltool.hpp b/contrib/Netgen/libsrc/stlgeom/stltool.hpp new file mode 100644 index 0000000000..ca3d6e2f14 --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/stltool.hpp @@ -0,0 +1,271 @@ +#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<Point3d>& 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 <int> * ArrayINTPTR; + +class STLGeometry; + +class STLChart +{ +private: + STLGeometry * geometry; + Array<int>* charttrigs; // trigs which only belong to this chart + Array<int>* outertrigs; // trigs which belong to other charts + Box3dTree * searchtree; // ADT containing outer trigs + + Array<twoint>* olimit; //outer limit of outer chart + Array<twoint>* ilimit; //outer limit of inner chart + + +public: + + STLChart(STLGeometry * ageometry); + 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<int> & 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<int>& trigs); + void DelChartTrigs(const Array<int>& 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; +}; + +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<Point<3> > & points, + const STLChart * achart); + + 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<STLBoundarySeg> boundary; +public: + STLBoundary(STLGeometry * ageometry); + // : boundary() {}; + + void Clear() {boundary.SetSize(0);}; + 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);} + + int TestSeg(const Point<3> & p1, const Point<3> & p2, const Vec<3> & sn, + double sinchartangle, int divisions, Array<Point<3> >& 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; +}; + +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; +}; + +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 diff --git a/contrib/Netgen/libsrc/stlgeom/stltopology.cpp b/contrib/Netgen/libsrc/stlgeom/stltopology.cpp new file mode 100644 index 0000000000..8547034f08 --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/stltopology.cpp @@ -0,0 +1,1067 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <gprim.hpp> + +#include <meshing.hpp> + +#include "stlgeom.hpp" + +namespace netgen +{ + + + STLTopology :: STLTopology() + : trias(), topedges(), points(), ht_topedges(NULL), + trigsperpoint(), neighbourtrigs() +{ + ; +} + +STLTopology :: ~STLTopology() +{ + ; +} + + + + +STLGeometry * STLTopology :: LoadBinary (istream & ist) +{ + STLGeometry * geom = new STLGeometry(); + Array<STLReadTriangle> 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; + + int cntface, j; + //int vertex = 0; + float f; + char spaces[nospaces+1]; + + for (cntface = 0; cntface < nofacets; cntface++) + { + if (cntface % 10000 == 9999) { PrintDot(); } + + FIOReadFloat(ist,f); normal(0) = f; + FIOReadFloat(ist,f); normal(1) = f; + FIOReadFloat(ist,f); normal(2) = f; + + for (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); + } + + + 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<STLReadTriangle> 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<Point<3> > 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) +{ + size_t i; + STLGeometry * geom = new STLGeometry(); + + Array<STLReadTriangle> readtrigs; + + char buf[100]; + Point<3> pts[3]; + Vec<3> normal; + + int cntface = 0; + int vertex = 0; + bool badnormals = 0; + + while (ist.good()) + { + ist >> buf; + + size_t n = strlen (buf); + for (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; + hnormal = Cross (pts[1]-pts[0], pts[2]-pts[0]); + hnormal.Normalize(); + + if (normal * hnormal < 0.5) + { + badnormals = 1; + } + } + + 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 (badnormals) + { + PrintWarning("File has normal vectors which differ extremly from geometry->correct with stldoctor!!!"); + } + + geom->InitSTLGeometry(readtrigs); + return geom; +} + + + + + + + + + + + + + +void STLTopology :: InitSTLGeometry(const Array<STLReadTriangle> & readtrigs) +{ + int i, k; + + // 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 (i = 0; i < readtrigs.Size(); i++) + for (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<int> pintersect; + + pointtol = boundingbox.Diam() * stldoctor.geom_tol_fact; + PrintMessage(5,"point tolerance = ", pointtol); + + for(i = 0; i < readtrigs.Size(); i++) + { + const STLReadTriangle & t = readtrigs[i]; + STLTriangle st; + // Vec<3> n = t.Normal(); + st.SetNormal (t.Normal()); + + for (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); + } + st[k] = foundpos; + } + + if ( (st[0] == st[1]) || + (st[0] == st[2]) || + (st[1] == st[2]) ) + { + PrintError("STL Triangle degenerated"); + } + else + { + AddTriangle(st); + } + + } + + 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<int> 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"); + + int i, j, k, l; + + // build up topology tables + + //int np = GetNP(); + int nt = GetNT(); + + INDEX_2_HASHTABLE<int> * oldedges = ht_topedges; + ht_topedges = new INDEX_2_HASHTABLE<int> (GetNP()+1); + topedges.SetSize(0); + + for (i = 1; i <= nt; i++) + { + STLTriangle & trig = GetTriangle(i); + + + for (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 (k = 1; k <= 3; k++) + if (othertrig.EdgeNum(k) == enr) + othertrig.NBTrigNum(k) = i; + } + else + { + enr = topedges.Append (STLTopEdge (pi1, pi2, i, 0)); + ht_topedges->Set (i2, enr); + trig.EdgeNum(j) = enr; + } + } + } + + + PrintMessage(5,"topology built, checking"); + + topology_ok = 1; + int ne = GetNTE(); + + for (i = 1; i <= nt; i++) + GetTriangle(i).flags.toperror = 0; + + for (i = 1; i <= nt; i++) + for (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 (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 (i = 1; i <= nt; i++) + { + const STLTriangle & t = GetTriangle (i); + for (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 (i = 1; i <= GetNT(); i++) + for (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 (i = 1; i <= ne; i++) + for (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 (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 (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 (l = 0; l < 3; l++) + if (trig2[l] - STLBASE == pi2) + { + hasboth = 1; + break; + } + if (!hasboth) continue; + + STLPointIndex pi4(0); + for (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 (i = 1; i <= GetNT(); i++) + for (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 (i = 1; i <= GetNT(); i++) + { + SetThreadPercent((double)i/(double)GetNT()*100.); + if (multithread.terminate) + { + PopStatus(); + return; + } + + for (k = 1; k <= 3; k++) + { + for (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<int> & 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 <int> oriented; + oriented.SetSize(GetNT()); + int i; + for (i = 1; i <= oriented.Size(); i++) + { + oriented.Elem(i) = 0; + } + + oriented.Elem(starttrig) = 1; + + int k; + + Array <int> list1; + list1.SetSize(0); + Array <int> 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!"); + } +} + + +} diff --git a/contrib/Netgen/libsrc/stlgeom/stltopology.hpp b/contrib/Netgen/libsrc/stlgeom/stltopology.hpp new file mode 100644 index 0000000000..fbb2394fd8 --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/stltopology.hpp @@ -0,0 +1,362 @@ +#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;} + + 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<Point<3> >& 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<Point<3> >& ap, + const Vec<3> & n, Point<3> & pp) const; + //project with the triangle's normal vector in plane + void ProjectInPlain(const Array<Point<3> > & 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<Point<3> >& ap, + const Vec<3> & nproj, + Point<3> & pp, Vec<3> & lam) const; + + int PointInside(const Array<Point<3> >& ap, const Point<3> & pp) const; + + //get nearest point on triangle and distance to it + double GetNearestPoint(const Array<Point<3> >& ap, + Point<3> & p3d) const; + + double Area(const Array<Point<3> >& ap) const; + + double MinHeight(const Array<Point<3> >& ap) const; + double MaxLength(const Array<Point<3> >& 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<STLTriangle> trias; + Array<STLTopEdge> topedges; + Array<Point<3> > points; + + // mapping of sorted pair of points to topedge + INDEX_2_HASHTABLE<int> * ht_topedges; + // mapping of node to trigs + TABLE<int> trigsperpoint; + // mapping of node to edges + TABLE<int> topedgesperpoint; + + // searchtree for trigs and points + + Box3dTree * 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 InitSTLGeometry (const Array<STLReadTriangle> & readtrigs); + + virtual void TopologyChanged() {}; //do some things, if topology changed! + + /// Generate topology tables + void FindNeighbourTrigs(); + + + void GetTrianglesInBox (const Box<3> & box, + Array<int> & trias) const; + + + int GetNP() const { return points.Size(); } + int AddPoint(const Point<3> & p) { return points.Append(p); } + 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<Point<3> >& 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; } + + void InvertTrig (int trig); + void DeleteTrig (int trig); + void OrientAfterTrig (int trig); + + + // Table will be constructed, if topology is not ok + /// neighbourtrigs for surfacetrigs + TABLE<int> 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 diff --git a/contrib/Netgen/libsrc/stlgeom/vsstl.cpp b/contrib/Netgen/libsrc/stlgeom/vsstl.cpp new file mode 100644 index 0000000000..338c305ddf --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/vsstl.cpp @@ -0,0 +1,1212 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <stlgeom.hpp> + +#include <meshing.hpp> +#include <visual.hpp> + + +#include "vsstl.hpp" + + +namespace netgen +{ + +/* +//mmm +#include "stlgeom/modeller.hpp" +*/ + +/* *********************** Draw STL Geometry **************** */ + +extern STLGeometry * stlgeometry; +extern AutoPtr<Mesh> 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(); + 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<MoTriangle> 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<twoint>& 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; + + + + + + /* *********************** 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(); + 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); + + + 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 (); + } + +} diff --git a/contrib/Netgen/libsrc/stlgeom/vsstl.hpp b/contrib/Netgen/libsrc/stlgeom/vsstl.hpp new file mode 100644 index 0000000000..d3841c8174 --- /dev/null +++ b/contrib/Netgen/libsrc/stlgeom/vsstl.hpp @@ -0,0 +1,53 @@ +#ifndef FILE_VSSTL +#define FILE_VSSTL + +/**************************************************************************/ +/* File: vsstl.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 05. Jan. 2011 */ +/**************************************************************************/ + +namespace netgen +{ + + class VisualSceneSTLGeometry : public VisualScene + { + Array<int> trilists; + class STLGeometry * stlgeometry; + + public: + VisualSceneSTLGeometry (); + virtual ~VisualSceneSTLGeometry (); + void SetGeometry (class STLGeometry * astlgeometry) { stlgeometry = astlgeometry; } + + virtual void BuildScene (int zoomall = 0); + virtual void DrawScene (); + }; + + + class VisualSceneSTLMeshing : public VisualScene + { + Array<int> trilists; + int selecttrig, nodeofseltrig; + class STLGeometry * stlgeometry; + + public: + VisualSceneSTLMeshing (); + 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 diff --git a/contrib/Netgen/libsrc/visualization/Makefile.am b/contrib/Netgen/libsrc/visualization/Makefile.am new file mode 100644 index 0000000000..5f2dff7eba --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/Makefile.am @@ -0,0 +1,11 @@ +noinst_HEADERS = meshdoc.hpp mvdraw.hpp vispar.hpp \ +visual.hpp vssolution.hpp + +include_HEADERS = soldata.hpp + +AM_CPPFLAGS = $(MPI_INCLUDES) -I$(top_srcdir)/libsrc/include -DOPENGL -D$(TOGL_WINDOWINGSYSTEM) $(OCCFLAGS) $(TCL_INCLUDES) +METASOURCES = AUTO +noinst_LIBRARIES = libvisual.a +libvisual_a_SOURCES = meshdoc.cpp mvdraw.cpp \ + vsfieldlines.cpp vsmesh.cpp vssolution.cpp importsolution.cpp +AM_CXXFLAGS = -DOPENGL diff --git a/contrib/Netgen/libsrc/visualization/importsolution.cpp b/contrib/Netgen/libsrc/visualization/importsolution.cpp new file mode 100644 index 0000000000..cf182d7120 --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/importsolution.cpp @@ -0,0 +1,129 @@ +// +// Read solution file +// + + +#include <mystdlib.h> + + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +#include <nginterface.h> + +namespace netgen +{ + + + +void ImportSolution (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", 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); + */ +} + + + +} diff --git a/contrib/Netgen/libsrc/visualization/meshdoc.cpp b/contrib/Netgen/libsrc/visualization/meshdoc.cpp new file mode 100644 index 0000000000..c2df277e10 --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/meshdoc.cpp @@ -0,0 +1,614 @@ +#ifndef NOTCL + +#include <mystdlib.h> + +#include <meshing.hpp> + +// #include "incvis.hpp" + + +#include <visual.hpp> + + +namespace netgen +{ + // #include "meshdoc.hpp" + + +MeshDoctorParameters meshdoctor; +VisualSceneMeshDoctor vsmeshdoc; + +extern AutoPtr<Mesh> 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; +} + + + + + +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(); + glMultMatrixf (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(); + glMultMatrixf (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 diff --git a/contrib/Netgen/libsrc/visualization/meshdoc.hpp b/contrib/Netgen/libsrc/visualization/meshdoc.hpp new file mode 100644 index 0000000000..65763385f1 --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/meshdoc.hpp @@ -0,0 +1,37 @@ + +class VisualSceneMeshDoctor : public VisualScene +{ + int filledlist; + int outlinelist; + int edgelist; + + int selelement, locpi; + int selpoint, selpoint2; + + // for edgemarking: + Array<int> edgedist; + int markedgedist; + + +public: + VisualSceneMeshDoctor (); + virtual ~VisualSceneMeshDoctor (); + + virtual void BuildScene (int zoomall = 0); + virtual void DrawScene (); + virtual void MouseDblClick (int px, int py); + + void SetMarkEdgeDist (int dist); + void ClickElement (int elnr); + void UpdateTables (); + int IsSegmentMarked (int segnr) const; +}; + +class MeshDoctorParameters +{ +public: + int active; +}; + + +extern MeshDoctorParameters meshdoctor; diff --git a/contrib/Netgen/libsrc/visualization/mvdraw.cpp b/contrib/Netgen/libsrc/visualization/mvdraw.cpp new file mode 100644 index 0000000000..d348fc7b66 --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/mvdraw.cpp @@ -0,0 +1,806 @@ +#include <mystdlib.h> +#include <myadt.hpp> +#include <meshing.hpp> + +#include <visual.hpp> +// #include <parallel.hpp> + + + +#ifndef WIN32 +#define GLX_GLXEXT_LEGACY + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> /* for XA_RGB_DEFAULT_MAP atom */ +// #include <GL/glx.h> // 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 + */ + + // texture for color decoding + // GLubyte * VisualScene :: colortexture = NULL; + GLuint VisualScene :: coltexname = 1; + int VisualScene :: ntexcols = -1; + + + float VisualScene :: lookatmat[16]; + float VisualScene :: transmat[16]; + float VisualScene :: rotmat[16]; + float VisualScene :: centermat[16]; + float VisualScene :: transformationmat[16]; + + int VisualScene :: selface; + int VisualScene :: selelement; + int VisualScene :: selpoint; + int VisualScene :: selpoint2; + int VisualScene :: locpi; + int VisualScene :: seledge; + + int VisualScene :: selecttimestamp; + + + 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(); + DLL_HEADER void Render () + { + 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); + glGetFloatv (GL_MODELVIEW_MATRIX, lookatmat); + + glLoadIdentity(); + glTranslatef(0.0f, 0.0f, -dist); + glGetFloatv (GL_MODELVIEW_MATRIX, transmat); + + glLoadIdentity(); + glGetFloatv (GL_MODELVIEW_MATRIX, rotmat); + + glScalef (1/rad, 1/rad, 1/rad); + glTranslated (-center.X(), -center.Y(), -center.Z()); + glGetFloatv (GL_MODELVIEW_MATRIX, centermat); + + glLoadIdentity(); + glMultMatrixf (lookatmat); + glMultMatrixf (transmat); + glMultMatrixf (rotmat); + glMultMatrixf (centermat); + glGetFloatv (GL_MODELVIEW_MATRIX, transformationmat); + + glPopMatrix(); + } + + + void VisualScene :: ArbitraryRotation (const Array<double> & alpha, const Array<Vec3d> & vec) + { + glPushMatrix(); + + glLoadIdentity(); + + for(int i=0; i<alpha.Size() && i<vec.Size(); i++) + { + glRotatef(alpha[i], vec[i].X(), vec[i].Y(), vec[i].Z()); + } + + glGetFloatv (GL_MODELVIEW_MATRIX, rotmat); + + glLoadIdentity(); + glMultMatrixf (lookatmat); + glMultMatrixf (transmat); + glMultMatrixf (rotmat); + glMultMatrixf (centermat); + glGetFloatv (GL_MODELVIEW_MATRIX, transformationmat); + + glPopMatrix(); + } + + + + void VisualScene :: ArbitraryRotation (const double alpha, const Vec3d & vec) + { + Array<double> a(1); a[0] = alpha; + Array<Vec3d> 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); + + + glGetFloatv (GL_MODELVIEW_MATRIX, rotmat); + + glLoadIdentity(); + glMultMatrixf (lookatmat); + glMultMatrixf (transmat); + glMultMatrixf (rotmat); + glMultMatrixf (centermat); + glGetFloatv (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); + glMultMatrixf (rotmat); + glGetFloatv (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); + + glMultMatrixf (transmat); + glGetFloatv (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); + glMultMatrixf (transmat); + glGetFloatv (GL_MODELVIEW_MATRIX, transmat); + break; + } + } + + glLoadIdentity(); + glMultMatrixf (lookatmat); + glMultMatrixf (transmat); + glMultMatrixf (rotmat); + glMultMatrixf (centermat); + glGetFloatv (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)); + glMultMatrixf (centermat); + glGetFloatv (GL_MODELVIEW_MATRIX, transformationmat); + glPopMatrix(); + } + + + void VisualScene :: SetClippingPlane () + { + if (vispar.clipenable) + { + Vec3d n = vispar.clipnormal; + n /= (n.Length()+1e-10); + clipplane[0] = n.X(); + clipplane[1] = n.Y(); + clipplane[2] = n.Z(); + clipplane[3] = -(Vec3d(center) * n) + rad * vispar.clipdist; + + glClipPlane(GL_CLIP_PLANE0, clipplane); + 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, 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); + } + + // 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, 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] = { 1 - backcolor, 1 - backcolor, 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); + glMultMatrixf (rotmat); + + glEnable (GL_COLOR_MATERIAL); + glDisable (GL_LIGHTING); + + glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); + + GLfloat textcol[3] = { 1 - backcolor, + 1 - backcolor, + 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] = { 1 - backcolor, + 1 - backcolor, + 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); + /* + + 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); + + vssolution.Broadcast (); + } +#endif + +} diff --git a/contrib/Netgen/libsrc/visualization/mvdraw.hpp b/contrib/Netgen/libsrc/visualization/mvdraw.hpp new file mode 100644 index 0000000000..211227cdec --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/mvdraw.hpp @@ -0,0 +1,245 @@ +#ifndef FILE_MVDRAW +#define FILE_MVDRAW + + +namespace netgen +{ + + /* + extern void InitDrawMesh (); + extern void DrawMesh (); + extern void MouseMove(int oldx, int oldy, + int newx, int newy, + char mode); + + extern void Render (); + */ + + + class VisualScene + { + protected: + static DLL_HEADER Point3d center; + static DLL_HEADER double rad; + + static float lookatmat[16]; + static float transmat[16]; + static float rotmat[16]; + static float centermat[16]; + static DLL_HEADER float transformationmat[16]; + + GLdouble clipplane[4]; + + int changeval; + static DLL_HEADER GLdouble backcolor; + + static int selface; + static int selelement; + static int selpoint; + static int selpoint2; + static int locpi; + static int seledge; + + static int selecttimestamp; + + public: + + // static GLubyte * colortexture; + static GLuint coltexname; + static int ntexcols; + // static bool linear_colors; + 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<double> & alpha, const Array<Vec3d> & 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, int typ = GL_DECAL); + 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 + }; + + + extern void MyOpenGLText (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<int> par_linelists; + Array<int> par_filledlists; +#endif + + + NgLock *lock; + + // int selface, selelement; + // int selpoint, selpoint2, locpi; + // int seledge; + + double minh, maxh; // for meshsize coloring + + public: + VisualSceneMesh (); + virtual ~VisualSceneMesh (); + + virtual void BuildScene (int zoomall = 0); + virtual void DrawScene (); + virtual void MouseDblClick (int px, int py); + + int SelectedFace () const + { return selface; } + void SetSelectedFace (int asf); + // { selface = asf; selecttimestamp = GetTimeStamp(); } + + int SelectedEdge () const + { return seledge; } + int SelectedElement () const + { return selelement; } + 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(); + }; + + + + class 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 float * transformationmat, + const Point3d & center, + const double rad, + const int displaylist, + int & selelement, int & selface, int & seledge, int & selpoint, + int & selpoint2, int & locpi); + + +} + + +#endif + diff --git a/contrib/Netgen/libsrc/visualization/soldata.hpp b/contrib/Netgen/libsrc/visualization/soldata.hpp new file mode 100644 index 0000000000..65d05ddafc --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/soldata.hpp @@ -0,0 +1,111 @@ +#ifndef FILE_SOLDATA +#define FILE_SOLDATA + + +namespace netgen +{ + + using namespace std; + + class DLL_HEADER 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 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 */, + double /* lam1 */, double /* lam2 */, + double * /* values */) + { + return false; + } + + + virtual bool GetSurfValue (int selnr, + const double xref[], const double x[], const double dxdxref[], + double * values) + { + return GetSurfValue (selnr, xref[0], xref[1], values); + } + + + virtual bool GetMultiSurfValue (int selnr, 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, &xref[i*sxref], &x[i*sx], &dxdxref[i*sdxdxref], &values[i*svalues]); + return res; + } + + + virtual int GetNumMultiDimComponents () + { + return 1; + } + + void SetMultiDimComponent (int mc) + { + if (mc >= GetNumMultiDimComponents()) mc = GetNumMultiDimComponents()-1; + if (mc < 0) mc = 0; + multidimcomponent = mc; + } + }; +} + +#endif + diff --git a/contrib/Netgen/libsrc/visualization/stlmeshing.cpp b/contrib/Netgen/libsrc/visualization/stlmeshing.cpp new file mode 100644 index 0000000000..452dbd928b --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/stlmeshing.cpp @@ -0,0 +1,1076 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <stlgeom.hpp> + +#include <meshing.hpp> +#ifndef NOTCL +#include <visual.hpp> +#endif + +namespace netgen +{ + +/* +//mmm +#include "stlgeom/modeller.hpp" +*/ + +/* *********************** Draw STL Geometry **************** */ + +extern STLGeometry * stlgeometry; +extern AutoPtr<Mesh> 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<MoTriangle> 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<twoint>& 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 + + + + +} diff --git a/contrib/Netgen/libsrc/visualization/vispar.hpp b/contrib/Netgen/libsrc/visualization/vispar.hpp new file mode 100644 index 0000000000..da13982633 --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/vispar.hpp @@ -0,0 +1,106 @@ +#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; + + 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; + + + int 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(); +}; +extern VisualizationParameters vispar; +} + +#endif diff --git a/contrib/Netgen/libsrc/visualization/visual.hpp b/contrib/Netgen/libsrc/visualization/visual.hpp new file mode 100644 index 0000000000..405c5b6be3 --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/visual.hpp @@ -0,0 +1,35 @@ +#ifndef FILE_VISUAL +#define FILE_VISUAL + +/* *************************************************************************/ +/* File: visual.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 02. Dec. 01 */ +/* *************************************************************************/ + +/* + +Visualization + +*/ + +#ifdef PARALLEL +#define PARALLELGL +#endif + +#include "../include/incvis.hpp" + +#include "vispar.hpp" +#include "mvdraw.hpp" +#include "soldata.hpp" + +#include <complex> + +namespace netgen +{ +#include "vssolution.hpp" +#include "meshdoc.hpp" +} + + +#endif diff --git a/contrib/Netgen/libsrc/visualization/vscsg.cpp b/contrib/Netgen/libsrc/visualization/vscsg.cpp new file mode 100644 index 0000000000..f4ef67d7c5 --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/vscsg.cpp @@ -0,0 +1,272 @@ +#ifndef NOTCL + +#include <mystdlib.h> +#include "incvis.hpp" + +#include <myadt.hpp> +#include <meshing.hpp> +#include <csg.hpp> +#include <stlgeom.hpp> + +#include <visual.hpp> + + +namespace netgen +{ + +/* *********************** Draw Geometry **************** */ + + extern Array<Point<3> > project1, project2; + + +extern AutoPtr<CSGeometry> geometry; + + +VisualSceneGeometry :: VisualSceneGeometry () + : VisualScene() +{ + selsurf = 0; +} + +VisualSceneGeometry :: ~VisualSceneGeometry () +{ + ; +} + +void VisualSceneGeometry :: SelectSurface (int aselsurf) +{ + selsurf = aselsurf; + DrawScene(); +} + + +void VisualSceneGeometry :: DrawScene () +{ + int i; + + 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(); + 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); + + glEnable (GL_NORMALIZE); + + for (i = 0; i < geometry->GetNTopLevelObjects(); i++) + { + const TopLevelObject * tlo = geometry -> GetTopLevelObject (i); + if (tlo->GetVisible() && !tlo->GetTransparent()) + { + float mat_col[] = { tlo->GetRed(), tlo->GetGreen(), 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 (i = 0; i < geometry->GetNTopLevelObjects(); i++) + { + const TopLevelObject * tlo = geometry -> GetTopLevelObject (i); + if (tlo->GetVisible() && tlo->GetTransparent()) + { + float mat_col[] = { tlo->GetRed(), tlo->GetGreen(), tlo->GetBlue(), transp }; + + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); + + glCallList (trilists[i]); + } + } + + glDisable (GL_POLYGON_OFFSET_FILL); + + /* + cout << "draw " << project1.Size() << " lines " << endl; + glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); + glLineWidth (1.0f); + glEnable (GL_COLOR_MATERIAL); + + glColor3f (1.0f, 0.0f, 0.0f); + + glBegin (GL_LINES); + for (int i = 0; i < project1.Size(); i++) + { + glVertex3dv (project1[i]); + glVertex3dv (project2[i]); + } + glEnd(); + */ + + + glPopMatrix(); + glDisable(GL_CLIP_PLANE0); + + + + /* + glFlush(); + + int err; + do + { + err = glGetError(); + // cout << "glerr,1 = " << err << endl; + } + while (err != GL_NO_ERROR); + + + // CreateTexture (0, 1, GL_DECAL); + CreateTexture (0, 1, GL_MODULATE); + glEnable (GL_TEXTURE_1D); + + float mat_col[] = { 1.0, 1.0, 1.0 }; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); + + glDisable (GL_BLEND); + glDisable (GL_COLOR_MATERIAL); + glEnable (GL_NORMALIZE); + + if (geometry->GetNTopLevelObjects()) + { + cout << "call list" << endl; + glCallList (trilists[0]); + } + + glColor3d (1.0, 1.0, 1.0); + + glBegin (GL_TRIANGLES); + glNormal3f (0, 0, 1); + SetOpenGlColor (-1.0, 0, 1, 0); + glVertex3f (0.0, 0.0, 0.0); + SetOpenGlColor (0.5, 0, 1, 0); + glNormal3f (0, 0, 1); + glVertex3f (1.0, 0.0, 0.0); + SetOpenGlColor (2.0, 0, 1, 0); + glNormal3f (0, 0, 1); + glVertex3f (0.0, 1.0, 0.0); + + glEnd (); + + cout << "trig drawn" << endl; + + glDisable (GL_TEXTURE_1D); + glDisable (GL_COLOR_MATERIAL); + glFlush(); + + cout << "glerr,2 = " << glGetError() << endl; + */ + + + + DrawCoordinateCross (); + DrawNetgenLogo (); + + glFinish(); +} + + +void VisualSceneGeometry :: BuildScene (int zoomall) +{ + 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) + { + glBegin (GL_TRIANGLES); + for (int j = 0; j < ta.GetNT(); j++) + { + for (int k = 0; k < 3; k++) + { + int pi = ta.GetTriangle(j)[k]; + glNormal3dv (ta.GetNormal (pi)); + glVertex3dv (ta.GetPoint(pi)); + } + } + glEnd (); + } + glEndList (); + } + +} + + + + + +} + + +#endif // NOTCL diff --git a/contrib/Netgen/libsrc/visualization/vsfieldlines.cpp b/contrib/Netgen/libsrc/visualization/vsfieldlines.cpp new file mode 100644 index 0000000000..e7201a483d --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/vsfieldlines.cpp @@ -0,0 +1,729 @@ +#ifndef NOTCL + +#include <mystdlib.h> +#include "incvis.hpp" + + +#include <myadt.hpp> +#include <meshing.hpp> +#include <csg.hpp> +#include <stlgeom.hpp> + +#include <visual.hpp> + + +namespace netgen +{ + + extern AutoPtr<Mesh> 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<int> size(2); + size[0] = 0; size[1] = 1; + a = new TABLE<double>(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<int> size(3); + size[0] = 0; size[1] = 1; size[2] = 2; + a = new TABLE<double>(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<int> size(4); + size[0] = 0; size[1] = 1; size[2] = 2; size[3] = 3; + a = new TABLE<double>(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; i<stepcount-1; i++) + val += h * a->Get(stepcount,i+1) * K[i]; + } + + + if(stepcount == steps) + { + val = startval; + for(int i=0; i<steps; i++) + val += h * b[i] * K[i]; + + if(adaptive) + { + if(adrun == 0) + { + stepcount = 0; + h *= 0.5; + adrun = 1; + valh = val; + } + else if (adrun == 1) + { + stepcount = 0; + startval_bak = startval; + startval = val; + startt_bak = startt; + startt += h;//0.5*h; + adrun = 2; + } + else if (adrun == 2) + { + Point3d valh2 = val; + val = valh2 + 1./(pow(2.,order)-1.) * (valh2 - valh); + Vec3d errvec = val - valh; + + double err = errvec.Length(); + + double fac = 0.7 * pow(tolerance/err,1./(order+1.)); + if(fac > 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; i<stepcount; i++) + val += h * a->Get(stepcount,i) * K[i]; + } + + return finished; + } + + + bool RKStepper :: FeedNextF(const Vec3d & f) + { + K[stepcount] = f; + stepcount++; + return true; + } + + + + void FieldLineCalc :: GenerateFieldLines(Array<Point3d> & potential_startpoints, const int numlines, const int gllist, + const double minval, const double maxval, const int logscale, double phaser, double phasei) + { + + + Array<Point3d> points; + Array<double> values; + Array<bool> drawelems; + Array<int> 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; i<potential_startpoints.Size(); i++) + { + int elnr = mesh.GetElementOfPoint(potential_startpoints[i],lami,true) - 1; + if(elnr == -1) + continue; + + mesh.SetPointSearchStartElement(elnr); + + if (mesh.GetDimension()==3) + vss.GetValues ( vsol, elnr, lami[0], lami[1], lami[2], values); + else + vss.GetSurfValues ( vsol, elnr, lami[0], lami[1], values); + + + VisualSceneSolution::RealVec3d ( values, v, vsol->iscomplex, phaser, phasei); + + sum += v.Length(); + } + + crit = sum/double(numlines); + } + + + int calculated = 0; + + cout << endl; + + + + + for(int i=0; i<potential_startpoints.Size(); i++) + { + cout << "\rFieldline Calculation " << int(100.*i/potential_startpoints.Size()) << "%"; cout.flush(); + + if(randomized) + SetCriticalValue((double(rand())/RAND_MAX)*crit); + + if(calculated >= numlines) break; + + Calc(potential_startpoints[i],points,values,drawelems,dirstart); + + bool usable = false; + + for(int j=1; j<dirstart.Size(); j++) + for(int k=dirstart[j-1]; k<dirstart[j]-1; k++) + { + if(!drawelems[k] || !drawelems[k+1]) continue; + + usable = true; + + // vss.SetOpenGlColor (0.5*(values[k]+values[k+1]), minval, maxval, logscale); + + /* + if (vss.usetexture == 1) + glTexCoord1f ( 0.5*(values[k]+values[k+1]) ); + else + */ + vss.SetOpenGlColor (0.5*(values[k]+values[k+1]) ); + vss.DrawCylinder (points[k], points[k+1], thickness); + } + + if(usable) calculated++; + } + cout << "\rFieldline Calculation " << 100 << "%" << endl; + + } + + + + FieldLineCalc :: FieldLineCalc(const Mesh & amesh, VisualSceneSolution & avss, const VisualSceneSolution::SolData * solution, + const double rel_length, const int amaxpoints, + const double rel_thickness, const double rel_tolerance, const int rk_type, const int adirection) : + mesh(amesh), vss(avss), vsol(solution), stepper(rk_type) + { + mesh.GetBox (pmin, pmax); + rad = 0.5 * Dist (pmin, pmax); + + + maxlength = (rel_length > 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<Point3d> & points, Array<double> & vals, Array<bool> & drawelems, Array<int> & 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, 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, 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 " <<dir << " reached the wall." << endl; + break; + } + + points.Append(newp); + vals.Append(v.Length()); + drawelems.Append(drawelem); + + if(points.Size() % 40 == 0 && points.Size() > 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<Point3d> & startpoints) + { + 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<Point3d> & startpoints) + { + 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<Point3d> & startpoints) + { + 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<Point3d> auxpoints(iparam); + + if (keyword == "box") + BuildFieldLinesFromBox(auxpoints); + else if (keyword == "line") + BuildFieldLinesFromLine(auxpoints); + + for(int i=0; i<iparam; i++) + { + startpoints[numpoints] = auxpoints[i]; + numpoints++; + } + } + + //cout << "startpoints " << startpoints << endl; + } + + delete infile; + + + + + } + + + void VisualSceneSolution :: BuildFieldLinesFromFace(Array<Point3d> & startpoints) + { + Array<SurfaceElementIndex> 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; i<elements_2d.Size(); i++) + { + const Element2d & elem = mesh->SurfaceElement(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() && tri<numtri; tri++) + { + + if(tri == 0) + { + v1 = mesh->Point(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<numloc; j++) + { + double s = double (rand()) / RAND_MAX; + double t = double (rand()) / RAND_MAX; + if(s+t > 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 () + { + 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<Point3d> 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 diff --git a/contrib/Netgen/libsrc/visualization/vsmesh.cpp b/contrib/Netgen/libsrc/visualization/vsmesh.cpp new file mode 100644 index 0000000000..240a7e738a --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/vsmesh.cpp @@ -0,0 +1,3445 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <meshing.hpp> +// #include <csg.hpp> + +#ifdef STLGEOM +#include <stlgeom.hpp> +#endif + + +// #include <parallel.hpp> + +#include <visual.hpp> + +namespace netgen +{ + extern AutoPtr<Mesh> 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 = GetTimeStamp(); + selecttimestamp = GetTimeStamp(); + filledtimestamp = GetTimeStamp(); + linetimestamp = GetTimeStamp(); + edgetimestamp = GetTimeStamp(); + pointnumbertimestamp = GetTimeStamp(); + + tettimestamp = GetTimeStamp(); + prismtimestamp = GetTimeStamp(); + hextimestamp = GetTimeStamp(); + pyramidtimestamp = GetTimeStamp(); + + badeltimestamp = GetTimeStamp(); + identifiedtimestamp = GetTimeStamp(); + domainsurftimestamp = GetTimeStamp(); + + + selface = -1; + selelement = -1; + locpi = 1; + selpoint = -1; + selpoint2 = -1; + seledge = -1; + + minh = 0.0; + maxh = 0.0; + } + + VisualSceneMesh :: ~VisualSceneMesh () + { + ; + } + + + void VisualSceneMesh :: DrawScene () + { + if (!mesh) + { + VisualScene::DrawScene(); + return; + } + + lock = NULL; + + static int timer = NgProfiler::CreateTimer ("VSMesh::DrawScene"); + + NgProfiler::RegionTimer reg (timer); + + 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(); + glMultMatrixf (transformationmat); + + GLdouble projmat[16]; + 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) + // for (int dest = 1; dest < ntasks; dest++) + // if (vispar.drawtetsdomain == dest) + 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(); + } + + + void VisualSceneMesh :: BuildScene (int zoomall) + { + 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<Element2d> 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] = { 1 - backcolor, + 1 - backcolor, + 1 - backcolor }; + glColor3fv (textcol); + glNormal3d (0, 0, 1); + glPushAttrib (GL_LIST_BIT); + // glListBase (fontbase); + + char buf[30]; + + if (vispar.drawpointnumbers) + for (int i = 1; i <= mesh->GetNP(); i++) + { + const Point3d & p = mesh->Point(i); + glRasterPos3d (p.X(), p.Y(), p.Z()); + + sprintf (buf, "%d", i); + + // 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<int> 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<int> v; + for (int i = 1; i <= mesh->GetNE(); i++) + { + // const ELEMENTTYPE & eltype = mesh->ElementType(i); + Array<int> 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 (int i = 1; i <= mesh->GetNE(); i++) + { + if (mesh->VolumeElement(i).flags.badel) + { + // copy to be thread-safe + Element el = mesh->VolumeElement (i); + 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 (int i = 1; i <= mesh->GetNSE(); i++) + { + Element2d el = mesh->SurfaceElement(i); + if (!el.BadElement()) + continue; + + int drawel = 1; + for (int j = 1; j <= el.GetNP(); j++) + if (!el.PNum(j)) + drawel = 0; + + 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 -> GetIdentifications() ) + { + INDEX_2_HASHTABLE<int> & idpts = + mesh->GetIdentifications().GetIdentifiedPoints(); + if (&idpts) + { + 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; + } + + + + + void VisualSceneMesh :: BuildFilledList (bool names) + { + 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<STLGeometry*> (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<SurfaceElementIndex> 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() + { + 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<STLGeometry*> (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() + { + if (!lock) + { + lock = new NgLock (mesh->Mutex()); + lock -> Lock(); + } + + if (edgetimestamp > mesh->GetTimeStamp () && 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); + 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() + { + + if (tettimestamp > mesh->GetTimeStamp () && + tettimestamp > vispar.clipplanetimestamp ) + 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<Element2d> faces; + + BitArray shownode(mesh->GetNP()); + if (vispar.clipenable) + { + 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 } + */ + }; + + static float tetcols_ghost[4][4]; + + for (int j = 0; j < 4; j++) + { + for (int i = 0; i < 3; i++) + tetcols_ghost[j][i] = tetcols[j][i]; + tetcols_ghost[j][3] = 0.3; + } + + + 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(); + + 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; + + if ( el.IsGhost() ) + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, tetcols_ghost[ind]); + else + 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<Point<3> > ploc ( (order+1)*(order+1) ); + Array<Point<3> > 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; + + glBegin (GL_TRIANGLE_STRIP); + + // Philippose - 16/02/2010 + // Add Mesh size based coloring of + // meshes also for the volume elements + if(vispar.colormeshsize) + { + 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]); + } + else // Do not color mesh based on mesh size + { + 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() + { + if (prismtimestamp > mesh->GetTimeStamp () && + prismtimestamp > vispar.clipplanetimestamp ) + 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<Element2d> 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() + { + if (hextimestamp > mesh->GetTimeStamp () && + hextimestamp > vispar.clipplanetimestamp ) + 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<Element2d> 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() + { + if (pyramidtimestamp > mesh->GetTimeStamp () && + pyramidtimestamp > vispar.clipplanetimestamp ) + 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<Element2d> faces; + + for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) + { + const Element & el = (*mesh)[ei]; + if (el.GetType() == PYRAMID && !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() + { + 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) + { + BuildFilledList (true); + + MouseDblClickSelect(px,py,clipplane,backcolor,transformationmat,center,rad, + filledlist,selelement,selface,seledge,selpoint,selpoint2,locpi); + + + 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 float * transformationmat, + const Point3d & center, + const double rad, + const int displaylist, + int & selelement, int & selface, int & seledge, int & selpoint, + int & selpoint2, int & locpi) + { + 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 (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(); + } + + + + +} + + diff --git a/contrib/Netgen/libsrc/visualization/vsocc.cpp b/contrib/Netgen/libsrc/visualization/vsocc.cpp new file mode 100644 index 0000000000..c16984ccc7 --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/vsocc.cpp @@ -0,0 +1,762 @@ +#ifndef NOTCL + +#ifdef OCCGEOMETRY + +#include <mystdlib.h> +#include <myadt.hpp> +#include <meshing.hpp> + +#include <occgeom.hpp> + +#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 <visual.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(); + 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 diff --git a/contrib/Netgen/libsrc/visualization/vssolution.cpp b/contrib/Netgen/libsrc/visualization/vssolution.cpp new file mode 100644 index 0000000000..8ea46ddf0a --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/vssolution.cpp @@ -0,0 +1,4537 @@ +#ifndef NOTCL +#include <mystdlib.h> +#include "incvis.hpp" + + +#include <myadt.hpp> +#include <meshing.hpp> +#include <csg.hpp> +#include <stlgeom.hpp> + +// #include <parallel.hpp> +#include <visual.hpp> + + +namespace netgen +{ + extern AutoPtr<Mesh> mesh; + extern VisualSceneMesh vsmesh; + + + VisualSceneSolution :: SolData :: SolData () + : name (0), data (0), solclass(0) + { ; } + + VisualSceneSolution :: SolData :: ~SolData () + { + delete [] name; + delete data; + delete solclass; + } + + + VisualSceneSolution :: VisualSceneSolution () + : VisualScene() + { + surfellist = 0; + linelist = 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 () + { + ClearSolutionData(); + } + + void VisualSceneSolution :: AddSolutionData (SolData * sd) + { + NgLock meshlock1 (mesh->MajorMutex(), 1); + + int funcnr = -1; + for (int i = 0; i < soldata.Size(); i++) + { + if (strcmp (soldata[i]->name, sd->name) == 0) + { + 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) + { + 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<int> 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 () + { + 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, GL_MODULATE); + + glClearColor(backcolor, backcolor, backcolor, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + SetLight(); + + glPushMatrix(); + glMultMatrixf (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 * vssolution.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) + { + SetClippingPlane (); + + glCallList (surfellist); + glCallList (surface_vector_list); + + glDisable(GL_CLIP_PLANE0); + } + + if (showclipsolution) + { + if (clipsolution == 1) + glCallList (clipplanelist_scal); + if (clipsolution == 2) + glCallList (clipplanelist_vec); + } + + + 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.drawoutline && !numisolines) + { + SetClippingPlane (); + glCallList (linelist); + glDisable(GL_CLIP_PLANE0); + } + + if (numisolines) + { + SetClippingPlane (); + glCallList (isolinelist); + + glDisable(GL_CLIP_PLANE0); + glCallList (clipplane_isolinelist); + } + + glPopMatrix(); + + glDisable(GL_CLIP_PLANE0); + DrawColorBar (minval, maxval, logscale, lineartexture); + + if (vispar.drawcoordinatecross) + DrawCoordinateCross (); + DrawNetgenLogo (); + + glFinish(); + + + // delete lock; + // mem_lock.UnLock(); + } + + + + 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]; + } + } + } + + + 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) + { + 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.clipplanetimestamp > 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) + { + if (linelist) + glDeleteLists (linelist, 1); + + linelist = glGenLists (1); + glNewList (linelist, GL_COMPILE); + + DrawSurfaceElementLines(); + + glEndList (); + + surfellinetimestamp = max2 (solutiontimestamp, mesh->GetTimeStamp()); + } + + + + 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.clipplanetimestamp || + clipplanetimestamp < solutiontimestamp) + { + + // cout << "clipsolution = " << clipsolution << endl; + if (vispar.clipenable && clipsolution == 2) + { + // lock->UnLock(); + NgLock mlock (mesh->Mutex(), 0); + mlock.UnLock(); + mesh->BuildElementSearchTree(); + mlock.Lock(); + + // lock->Lock(); + } + + + if (vispar.clipenable && clipsolution == 1 && sol) + DrawClipPlaneTrigs (); + + if (clipplanelist_vec) + glDeleteLists (clipplanelist_vec, 1); + + clipplanelist_vec = glGenLists (1); + glNewList (clipplanelist_vec, GL_COMPILE); + + if (vispar.clipenable && clipsolution == 2 && vsol) + { + SetTextureMode (usetexture); + + if (autoscale) + GetMinMax (vecfunction, 0, minval, maxval); + + Array<ClipPlanePoint> 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); + + 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; i<mesh->GetNumPointCurves(); i++) + { + Box3d box; + box.SetPoint(mesh->GetPointCurvePoint(i,0)); + for(int j=1; j<mesh->GetNumPointsOfPointCurve(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; j<mesh->GetNumPointsOfPointCurve(i)-1; j++) + { + DrawCylinder(mesh->GetPointCurvePoint(i,j), + mesh->GetPointCurvePoint(i,j+1), + thick); + } + } + glEndList(); + } + + } + + + if ( + numisolines && + (clipplanetimestamp < vispar.clipplanetimestamp || + 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]; + +#ifdef PARALLEL + // parallel visualization --> dont draw ghost elements + if ( el . IsGhost() ) continue; +#endif + 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, 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, 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, vy, vtwist, 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, 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, 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.clipenable && clipsolution == 1 && sol) + { + clipplane_isolinelist = glGenLists (1); + glNewList (clipplane_isolinelist, GL_COMPILE); + + Array<ClipPlaneTrig> cpt; + Array<ClipPlanePoint> pts; + GetClippingPlaneTrigs (cpt, pts); + bool drawelem; + + glNormal3d (-clipplane[0], -clipplane[1], -clipplane[2]); + + 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, + // trig.points[1].p, + // trig.points[2].p, + vali[0], vali[1], vali[2]); + } + glEndList (); + } + glEnd(); + } + + clipplanetimestamp = max2 (vispar.clipplanetimestamp, solutiontimestamp); + } + + + + void VisualSceneSolution :: DrawSurfaceElements () + { + static int timer = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements"); + 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 + + + + 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 }; + 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<Point<2> > pref (npt); + Array<Point<3> > points (npt); + Array<Mat<3,2> > dxdxis (npt); + Array<Vec<3> > nvs(npt); + Array<double> values(npt); + + Array<double> mvalues(npt); + if (sol && sol->draw_surface) mvalues.SetSize (npt * sol->components); + + Array<complex<double> > valuesc(npt); + + for (SurfaceElementIndex sei = 0; sei < nse; sei++) + { + const Element2d & el = (*mesh)[sei]; + + if ( el . IsGhost() ) 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() == QUAD || el.GetType() == QUAD6 ) + { + 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]; + Mat<3,2> dxdxi; + + mesh->GetCurvedElements(). + CalcSurfaceTransformation (xref, sei, points[ii], dxdxi); + nvs[ii] = Cross (dxdxi.Col(0), dxdxi.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; + } + + 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, pref[ii](0), pref[ii](1), scalcomp, valuesc[ii]); + else + for (int ii = 0; ii < npt; ii++) + drawelem = GetSurfValue (sol, sei, pref[ii](0), pref[ii](1), scalcomp, values[ii]); + } + + if (deform) + for (int ii = 0; ii < npt; ii++) + points[ii] += GetSurfDeformation (sei, 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 + glColor3fv (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; + + for(SurfaceElementIndex sei = 0; sei < nse; sei++) + { + const Element2d & el = (*mesh)[sei]; + + if ( el . IsGhost() ) 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 ) + { + 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, 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, pref[ii](0), pref[ii](1)); + + int save_usetexture = usetexture; + if (!drawelem) + { + usetexture = 0; + SetTextureMode (usetexture); + } + + 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 + glColor3fv (col_grey); + + glNormal3dv (nvs[hi]); + glVertex3dv (points[hi]); + } + glEnd(); + } + if (!drawelem && (usetexture != save_usetexture)) + { + usetexture = save_usetexture; + SetTextureMode (usetexture); + } + } + } + glEndList (); + + +#ifdef PARALLELGL + glFinish(); + if (id > 0) + MyMPI_Send (surfellist, 0, MPI_TAG_VIS); +#endif + } + + + void VisualSceneSolution :: DrawSurfaceElementLines () + { + glLineWidth (1.0f); + // glNormal3d (1, 0, 0); + + int nse = mesh->GetNSE(); + + CurvedElements & curv = mesh->GetCurvedElements(); + + int n = 1 << subdivisions; + ArrayMem<Point<2>, 65> ptsloc(n+1); + ArrayMem<Point<3>, 65> ptsglob(n+1); + + double trigpts[3][2] = { { 0, 0 }, { 1, 0 }, { 0, 1} }; + double trigvecs[3][2] = { { 1, 0 }, { -1,1 }, { 0, -1} }; + + double quadpts[4][2] = { { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1} }; + double quadvecs[4][2] = { { 1, 0 }, { 0, 1 }, { -1, 0}, { 0, -1} }; + + for (SurfaceElementIndex sei = 0; sei < nse; sei++) + { + Element2d & el = (*mesh)[sei]; + + if ( el . IsGhost() ) continue; + + // bool curved = curv.IsSurfaceElementCurved (sei); + + int nv = (el.GetType() == TRIG || el.GetType() == TRIG6) ? 3 : 4; + /* + Point<3> p1, p2, p3, p4; + if (!curved) + { + p1 = (*mesh)[el[0]]; + p2 = (*mesh)[el[1]]; + p3 = (*mesh)[el[2]]; + if (nv == 4) p4 = (*mesh)[el[3]]; + } + */ + + 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); + + // if (curved) + { + 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, ptsloc[ix](0), ptsloc[ix](1)); + glVertex3dv (ptsglob[ix]); + } + } + /* + else + { + for (int ix = 0; ix <= n; ix++) + { + Point<2> p = p0 + (double(ix) / n) * vtau; + + Point<3> pnt; + + if (nv == 3) + pnt = p3 + p(0) * (p1-p3) + p(1) * (p2-p3); + else + pnt = p1 + p(0) * (p2-p1) + p(1) * (p4-p1) + p(0)*p(1) * ( (p1-p2)+(p3-p4) ); + + if (deform) + pnt += GetSurfDeformation (sei, p(0), p(1) ); + + glVertex3dv (pnt); + } + } + */ + glEnd (); + } + } + } + + + + + + + + + + void VisualSceneSolution :: DrawIsoSurface(const SolData * sol, + const SolData * vsol, + int comp) + { + 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<Point<3> > grid(n3); + Array<Point<3> > locgrid(n3); + Array<Mat<3,3> > trans(n3); + Array<double> val(n3); + Array<Vec<3> > grads(n3); + Array<int> compress(n3); + + MatrixFixWidth<3> pointmat(8); + grads = 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; + + if ( (*mesh)[ei] . IsGhost() ) 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; + + 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; + + if (vsol) + GetValues (vsol, ei, &locgrid[i](0), &grid[i](0), &trans[i](0), &grads[i](0)); + grads[i] *= -1; + + + if (val[i] > 0) + has_pos = 1; + else + has_neg = 1; + } + + if (!has_pos || !has_neg) continue; + + 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]]; + + 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]]); + + 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) + { + 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)); + + Vec<3> v; + double values[6]; + bool 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); // (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 () + { + 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 . IsGhost() ) continue; + + 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, 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 + { +#ifdef PARALLEL + if (id == 0) + { + MyMPI_SendCmd ("redraw"); + MyMPI_SendCmd ("getminmax"); + } + MyMPI_Bcast (funcnr); + MyMPI_Bcast (comp); +#endif + + const SolData * sol; + double val; + bool considerElem; + + bool hasit = false; + minv = 0; maxv = 1; + if (funcnr != -1) + { + sol = soldata[funcnr]; + + if (sol->draw_volume) + { + int ne = mesh->GetNE(); + for (int i = 0; i < ne; i++) + { + considerElem = GetValue (sol, i, 0.333, 0.333, 0.333, comp, val); + if (considerElem) + { + if (val > maxv || !hasit) + maxv = val; + if (val < minv || !hasit) + minv = val; + hasit = true; + } + } + } + if (sol->draw_surface) + { + int nse = mesh->GetNSE(); + for (int i = 0; i < nse; i++) + { + ELEMENT_TYPE type = mesh->SurfaceElement(i+1).GetType(); + if (type == QUAD) + considerElem = GetSurfValue (sol, i, 0.5, 0.5, comp, val); + else + considerElem = GetSurfValue (sol, i, 0.3333333, 0.3333333, comp, val); + if (considerElem) + { + if (val > maxv || !hasit) + maxv = val; + if (val < minv || !hasit) + minv = val; + hasit = true; + } + } + } + } + if (minv == maxv) maxv = minv+1e-6; + +#ifdef PARALLEL + if ((ntasks > 1) && (id == 0)) + { + minv = 1e99; + maxv = -1e99; + } + 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 + { + + double lam1 = xref[0]; + double lam2 = xref[1]; + double lam3 = xref[2]; + + val = 0; + bool ok = 0; + + + if (comp == 0) + { + ArrayMem<double,20> 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: + { + 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: + { + 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 handled 7234" << endl; + } + return 0; + } + + + + bool VisualSceneSolution :: + GetValue (const SolData * data, ElementIndex elnr, + double lam1, double lam2, double lam3, + int comp, double & val) const + { + + val = 0; + bool ok = 0; + + if (comp == 0) + { + ArrayMem<double,20> 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: + { + 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<double> & val) const + { + 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<double> (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 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, 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, + double lam1, double lam2, + double * values) const + { + bool ok = false; + switch (data->soltype) + { + case SOL_VIRTUALFUNCTION: + { + ok = data->solclass->GetSurfValue (selnr, lam1, lam2, values); + // ok = 1; + // values[0] = 1.0; + break; + } + default: + { + for (int i = 0; i < data->components; i++) + ok = GetSurfValue (data, selnr, lam1, lam2, i+1, values[i]); + } + } + return ok; + } + + + bool VisualSceneSolution :: + GetSurfValues (const SolData * data, SurfaceElementIndex selnr, + 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, xref, x, dxdxref, values); + break; + } + default: + { + for (int i = 0; i < data->components; i++) + ok = GetSurfValue (data, selnr, xref[0], xref[1], i+1, values[i]); + } + } + return ok; + } + + bool VisualSceneSolution :: + GetMultiSurfValues (const SolData * data, SurfaceElementIndex elnr, 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, npt, xref, sxref, x, sx, dxdxref, sdxdxref, val, sval); + else + for (int i = 0; i < npt; i++) + drawelem = GetSurfValues (data, elnr, 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<d; i++) + { + for (int j=d-1; i<j; j--) + { + if ( abs(ev(j)) > 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<double> VisualSceneSolution :: ExtractValueComplex (const SolData * data, int comp, double * values) const + { + if (!data->iscomplex) + return values[comp-1]; + else + return complex<double> (values[comp-1], values[comp]); + } + + + + + bool VisualSceneSolution :: + GetSurfValueComplex (const SolData * data, SurfaceElementIndex selnr, + double lam1, double lam2, + int comp, complex<double> & val) const + { + switch (data->soltype) + { + case SOL_VIRTUALFUNCTION: + { + ArrayMem<double,20> values(data->components); + bool ok; + + ok = data->solclass->GetSurfValue (selnr, lam1, lam2, &values[0]); + + if (ok) + { + if (!data->iscomplex) + val = values[comp-1]; + else + val = complex<double> (values[comp-1], values[comp]); + } + + return ok; + } + default: + cerr << "case not implementd 6565" << endl; + } + return 0; + } + + bool VisualSceneSolution :: + GetSurfValue (const SolData * data, SurfaceElementIndex selnr, + double lam1, double lam2, + int comp, double & val) const + { + bool ok; + if (comp == 0) + { + val = 0; + ArrayMem<double,20> values(data->components); + ok = GetSurfValues (data, selnr, lam1, lam2, &values[0]); + val = ExtractValue (data, 0, &values[0]); + return ok; + } + + + switch (data->soltype) + { + case SOL_VIRTUALFUNCTION: + { + + ArrayMem<double,20> values(data->components); + bool ok; + + ok = data->solclass->GetSurfValue (selnr, 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: + { + 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: + 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]; + 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: + { + val = (*mesh)[selnr].TestRefinementFlag(); + return 1; + } + + case SOL_ELEMENT_ORDER: + { + val = (*mesh)[selnr].GetOrder(); + return 1; + } + + } + return 0; + } + + + + + + + + + + + + + bool VisualSceneSolution :: + GetSurfValue (const SolData * data, SurfaceElementIndex selnr, + const double xref[], const double x[], const double dxdxref[], + int comp, double & val) const + { + double lam1 = xref[0], lam2 = xref[1]; + + bool ok; + if (comp == 0) + { + val = 0; + ArrayMem<double,20> values(data->components); + ok = GetSurfValues (data, selnr, xref, x, dxdxref, &values[0]); + val = ExtractValue (data, 0, &values[0]); + return ok; + } + + + switch (data->soltype) + { + case SOL_VIRTUALFUNCTION: + { + ArrayMem<double,20> 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, 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: + 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, double lam1, double lam2) const + { + Vec<3> def; + if (deform && vecfunction != -1) + { + GetSurfValues (soldata[vecfunction], elnr, lam1, lam2, &def(0)); + 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, lam1, lam2, scalcomp, def(2)); + def *= scaledeform; + } + else + def = 0; + return def; + } + + void VisualSceneSolution :: GetPointDeformation (int pnum, Point<3> & p, + SurfaceElementIndex elnr) const + { + 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<ClipPlaneTrig> & trigs, + Array<ClipPlanePoint> & pts) + { + static int timer1 = NgProfiler::CreateTimer ("ClipPlaneTrigs1"); + static int timer2 = NgProfiler::CreateTimer ("ClipPlaneTrigs2"); + static int timer3 = NgProfiler::CreateTimer ("ClipPlaneTrigs3"); + static int timer4 = NgProfiler::CreateTimer ("ClipPlaneTrigs4"); + + + 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<Element> loctets; + // Array<Element> loctetsloc; + // Array<Point<3> > pointsloc; + + int n = 1 << subdivisions; + int n3 = (n+1)*(n+1)*(n+1); + + Array<Point<3> > grid(n3); + Array<Point<3> > locgrid(n3); + Array<Mat<3,3> > trans(n3); + Array<double> val(n3); + Array<int> compress(n3); + + + for (ElementIndex ei = 0; ei < ne; ei++) + { + int first_point_of_element = pts.Size(); + +#ifdef PARALLEL + // parallel visualization --> dont draw ghost elements + if ( (*mesh)[ei] . IsGhost() ) continue; +#endif + + 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) + { + const Element & el = (*mesh)[ei]; + + int ii = 0; + int cnt_valid = 0; + + NgProfiler::StartTimer (timer2); + + + 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: + 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: + 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); + 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) cnt_valid = n3; + + locgrid.SetSize(cnt_valid); + + NgProfiler::StopTimer (timer2); + NgProfiler::RegionTimer reg4(timer4); + + if (mesh->GetCurvedElements().IsHighOrder()) + { + mesh->GetCurvedElements(). + CalcMultiPointElementTransformation (&locgrid, ei, &grid, 0); + } + else + { + 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 = 0, has_neg = 0; + + 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]; + + if (val[i] > 0) + has_pos = 1; + else + has_neg = 1; + } + + if (!has_pos || !has_neg) continue; + + + 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]]; + + 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 = 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]]; + + 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) ) + { + edgelam[j] = nodevali[lpi2] / (nodevali[lpi2] - nodevali[lpi1]); + Point<3> p1 = grid[teti[lpi1]]; + Point<3> p2 = grid[teti[lpi2]]; + + edgep[j] = p1 + (1-edgelam[j]) * (p2-p1); + + 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; + } + // cpt.points[k].p = edgep[ednr]; + + int pi1 = edgei[ednr][0]; + int pi2 = edgei[ednr][1]; + Point<3> p1 = locgrid[teti[pi1]]; + Point<3> p2 = locgrid[teti[pi2]]; + + // cpt.points[k].lami = p2 + edgelam[ednr] * (p1-p2); + + ClipPlanePoint cppt; + cppt.elnr = ei; + cppt.p = edgep[ednr]; + cppt.lami = p2 + edgelam[ednr] * (p1-p2); + + int pnr = -1; + + for (int l = first_point_of_element; l < pts.Size(); l++) + if (fabs (cppt.lami(0)-pts[l].lami(0)) < 1e-8 && + fabs (cppt.lami(1)-pts[l].lami(1)) < 1e-8 && + fabs (cppt.lami(2)-pts[l].lami(2)) < 1e-8) + { + pnr = l; + break; + } + + if (pnr == -1) + pnr = pts.Append (cppt)-1; + + 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) + return; + } + + } + } + + void VisualSceneSolution :: GetClippingPlaneGrid (Array<ClipPlanePoint> & pts) + { + 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 () + { +#ifdef PARALLELGL + + if (id == 0 && ntasks > 1) + { + InitParallelGL(); + + Array<int> 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<ClipPlaneTrig> trigs; + Array<ClipPlanePoint> 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]; + + + + 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<double> vals(maxlpnr+1); + Array<complex<double> > valsc(maxlpnr+1); + Array<int> elnrs(maxlpnr+1); + Array<bool> trigok(maxlpnr+1); + Array<Point<3> > locpoints(maxlpnr+1); + Array<Point<3> > globpoints(maxlpnr+1); + Array<Mat<3> > jacobi(maxlpnr+1); + Array<double> mvalues( (maxlpnr+1) * sol->components); + trigok = false; + elnrs = -1; + + Point<3> p[3]; + // double val[3]; + complex<double> valc[3]; + int lastelnr = -1; + int nlp = -1; + + for (int i = 0; i < trigs.Size(); i++) + { + bool ok = true; + 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, 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; + 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<double> (mvalues[ii*sol->components], + mvalues[ii*sol->components+1]); + } + + 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 + }; + 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 + }; + + + 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_Type_create_struct (15, blocklen, displ, types, &type); + MPI_Type_commit ( &type ); + + MPI_Bcast (this, 1, type, 0, MPI_COMM_WORLD); + MPI_Type_free (&type); + + /* + MyMPI_Bcast (usetexture); + MyMPI_Bcast (clipsolution); + MyMPI_Bcast (scalfunction); + MyMPI_Bcast (scalcomp); + MyMPI_Bcast (vecfunction); + MyMPI_Bcast (gridsize); + + MyMPI_Bcast (autoscale); + MyMPI_Bcast (logscale); + MyMPI_Bcast (minval); + MyMPI_Bcast (maxval); + MyMPI_Bcast (numisolines); + MyMPI_Bcast (subdivisions); + + MyMPI_Bcast (clipplane[0]); + MyMPI_Bcast (clipplane[1]); + MyMPI_Bcast (clipplane[2]); + MyMPI_Bcast (clipplane[3]); + */ + } + +#endif + + + int Ng_Vis_Set (ClientData clientData, + Tcl_Interp * interp, + int argc, tcl_const char *argv[]) + + { + 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) == pointpos-1) && + (strncmp (vssolution.soldata[i]->name, 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, vecname) == 0) + { + vssolution.vecfunction = i; + //cout << "set vecfunction to " << i << endl; + } + if (strcmp (vssolution.soldata[i]->name, fieldlines_vecname) == 0) + { + vssolution.fieldlines_vecfunction = i; + //cout << "set fieldlines-vecfunction to " << i << endl; + } + } + + 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; + + 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, 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); + } + + 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); + 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) + { + sprintf (buf, "%d", mesh->GetDimension()); + } + } + + Tcl_SetResult (interp, buf, TCL_STATIC); + 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; + } +} + +#endif // NOTCL diff --git a/contrib/Netgen/libsrc/visualization/vssolution.hpp b/contrib/Netgen/libsrc/visualization/vssolution.hpp new file mode 100644 index 0000000000..9bf1b78de4 --- /dev/null +++ b/contrib/Netgen/libsrc/visualization/vssolution.hpp @@ -0,0 +1,430 @@ +#ifndef FILE_VSSOLUTION +#define FILE_VSSOLUTION + + + +#ifndef SMALLLIB +#ifndef NOTCL + +extern +void ImportSolution (const char * filename); + +extern int Ng_Vis_Set (ClientData clientData, + Tcl_Interp * interp, + int argc, tcl_const char *argv[]); +#endif +#endif + +class FieldLineCalc; + +class 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; + }; + + + int surfellist; + int linelist; + 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<double> 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<int> par_linelists; + Array<int> par_surfellists; +#endif + + +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 (); + + char * 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*> 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<Point3d> & startpoints); + void BuildFieldLinesFromFace(Array<Point3d> & startpoints); + void BuildFieldLinesFromBox(Array<Point3d> & startpoints); + void BuildFieldLinesFromLine(Array<Point3d> & startpoints); + +public: + VisualSceneSolution (); + virtual ~VisualSceneSolution (); + + virtual void BuildScene (int zoomall = 0); + virtual void DrawScene (); + virtual void MouseDblClick (int px, int py); + + 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 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; + +private: + void GetClippingPlaneTrigs (Array<ClipPlaneTrig> & trigs, Array<ClipPlanePoint> & pts); + void GetClippingPlaneGrid (Array<ClipPlanePoint> & 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<double> & 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 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, + double lam1, double lam2, + int comp, double & val) const; + + bool GetSurfValue (const SolData * data, SurfaceElementIndex elnr, + const double xref[], const double x[], const double dxdxref[], + int comp, double & val) const; + + + bool GetSurfValueComplex (const SolData * data, SurfaceElementIndex elnr, + double lam1, double lam2, + int comp, complex<double> & val) const; + + bool GetSurfValues (const SolData * data, SurfaceElementIndex elnr, + double lam1, double lam2, + double * values) const; + + bool GetSurfValues (const SolData * data, SurfaceElementIndex elnr, + const double xref[], const double x[], const double dxdxref[], + double * values) const; + + bool GetMultiSurfValues (const SolData * data, SurfaceElementIndex elnr, 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<double> ExtractValueComplex (const SolData * data, int comp, double * values) const; + + + Vec<3> GetDeformation (ElementIndex elnr, const Point<3> & p) const; + Vec<3> GetSurfDeformation (SurfaceElementIndex selnr, 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 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; + +#ifndef SMALLLIB +#ifndef NOTCL + + friend int Ng_Vis_Set (ClientData clientData, + Tcl_Interp * interp, + int argc, tcl_const char *argv[]); + +#endif +#endif + + +#ifdef PARALLELGL + void Broadcast (); +#endif + + +}; + + + + +class RKStepper +{ +private: + Array<double> c,b; + TABLE<double> *a; + int steps; + int order; + + double tolerance; + + Array<Vec3d> 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<Point3d> & points, Array<double> & vals, Array<bool> & drawelems, Array<int> & dirstart); + + void GenerateFieldLines(Array<Point3d> & potential_startpoints, const int numlines, const int gllist, + const double minval, const double maxval, const int logscale, double phaser, double phasei); +}; + + + + +extern VisualSceneSolution vssolution; + + + + +#endif + -- GitLab