From 5b0535a9d30ced6cd7487a14f3fcbed11ebe10b1 Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Sat, 26 Jun 2004 17:58:16 +0000 Subject: [PATCH] Merged Netgen 4.3.1: a Delaunay/Frontal 2D/3D mesh generator. Thanks a lot to Nicolas Tardieu for this! --- Common/CommandLine.cpp | 13 +- Geo/GeoUtils.cpp | 4 +- Makefile | 4 +- Mesh/3D_Mesh.cpp | 11 +- Mesh/3D_Mesh_Netgen.cpp | 179 + Mesh/Makefile | 18 +- Mesh/Mesh.h | 9 +- Netgen/COPYING.LIB | 504 +++ Netgen/Makefile | 2926 ++++++++++++++ Netgen/NEWS | 9 + Netgen/README.GMSH | 69 + Netgen/VERSION | 1 + Netgen/libsrc/Makefile | 38 + Netgen/libsrc/csg/Makefile | 26 + Netgen/libsrc/csg/algprim.cpp | 1371 +++++++ Netgen/libsrc/csg/algprim.hpp | 331 ++ Netgen/libsrc/csg/brick.cpp | 409 ++ Netgen/libsrc/csg/brick.hpp | 97 + Netgen/libsrc/csg/bspline2d.cpp | 243 ++ Netgen/libsrc/csg/csg.hpp | 43 + Netgen/libsrc/csg/csgeom.cpp | 1067 +++++ Netgen/libsrc/csg/csgeom.hpp | 241 ++ Netgen/libsrc/csg/csgparser.cpp | 1186 ++++++ Netgen/libsrc/csg/csgparser_dalibor.cpp | 1111 ++++++ Netgen/libsrc/csg/csgscanner.cpp | 205 + Netgen/libsrc/csg/curve2d.cpp | 78 + Netgen/libsrc/csg/curve2d.hpp | 59 + Netgen/libsrc/csg/edgeflw.cpp | 1399 +++++++ Netgen/libsrc/csg/edgeflw.hpp | 90 + Netgen/libsrc/csg/explicitcurve2d.cpp | 160 + Netgen/libsrc/csg/explicitcurve2d.hpp | 109 + Netgen/libsrc/csg/extrusion.cpp | 175 + Netgen/libsrc/csg/extrusion.hpp | 89 + Netgen/libsrc/csg/gencyl.cpp | 209 + Netgen/libsrc/csg/gencyl.hpp | 64 + Netgen/libsrc/csg/genmesh.cpp | 709 ++++ Netgen/libsrc/csg/geometry.cpp | 1792 +++++++++ Netgen/libsrc/csg/geoml.hpp | 16 + Netgen/libsrc/csg/identify.cpp | 1483 +++++++ Netgen/libsrc/csg/identify.hpp | 173 + Netgen/libsrc/csg/lex.yy.cpp | 1834 +++++++++ Netgen/libsrc/csg/manifold.cpp | 14 + Netgen/libsrc/csg/manifold.hpp | 22 + Netgen/libsrc/csg/meshsurf.cpp | 178 + Netgen/libsrc/csg/meshsurf.hpp | 85 + Netgen/libsrc/csg/polyhedra.cpp | 288 ++ Netgen/libsrc/csg/polyhedra.hpp | 72 + Netgen/libsrc/csg/revolution.cpp | 151 + Netgen/libsrc/csg/revolution.hpp | 65 + Netgen/libsrc/csg/singularref.cpp | 134 + Netgen/libsrc/csg/singularref.hpp | 45 + Netgen/libsrc/csg/solid.cpp | 1285 ++++++ Netgen/libsrc/csg/solid.hpp | 163 + Netgen/libsrc/csg/specpoin.cpp | 1369 +++++++ Netgen/libsrc/csg/specpoin.hpp | 143 + Netgen/libsrc/csg/spline3d.cpp | 355 ++ Netgen/libsrc/csg/spline3d.hpp | 92 + Netgen/libsrc/csg/surface.cpp | 380 ++ Netgen/libsrc/csg/surface.hpp | 300 ++ Netgen/libsrc/csg/triapprox.cpp | 62 + Netgen/libsrc/csg/triapprox.hpp | 60 + Netgen/libsrc/general/Makefile | 12 + Netgen/libsrc/general/array.cpp | 75 + Netgen/libsrc/general/array.hpp | 471 +++ Netgen/libsrc/general/autoptr.hpp | 31 + Netgen/libsrc/general/bitarray.cpp | 132 + Netgen/libsrc/general/bitarray.hpp | 207 + Netgen/libsrc/general/dynamicmem.cpp | 117 + Netgen/libsrc/general/dynamicmem.hpp | 94 + Netgen/libsrc/general/flags.cpp | 330 ++ Netgen/libsrc/general/flags.hpp | 83 + Netgen/libsrc/general/hashtabl.cpp | 293 ++ Netgen/libsrc/general/hashtabl.hpp | 931 +++++ Netgen/libsrc/general/moveablemem.cpp | 241 ++ Netgen/libsrc/general/moveablemem.hpp | 97 + Netgen/libsrc/general/myadt.hpp | 43 + Netgen/libsrc/general/mystring.cpp | 383 ++ Netgen/libsrc/general/mystring.hpp | 193 + Netgen/libsrc/general/ngexception.cpp | 33 + Netgen/libsrc/general/ngexception.hpp | 30 + Netgen/libsrc/general/optmem.cpp | 59 + Netgen/libsrc/general/optmem.hpp | 36 + Netgen/libsrc/general/parthreads.cpp | 40 + Netgen/libsrc/general/parthreads.hpp | 126 + Netgen/libsrc/general/seti.cpp | 70 + Netgen/libsrc/general/seti.hpp | 45 + Netgen/libsrc/general/sort.cpp | 74 + Netgen/libsrc/general/sort.hpp | 18 + Netgen/libsrc/general/spbita2d.cpp | 172 + Netgen/libsrc/general/spbita2d.hpp | 56 + Netgen/libsrc/general/stack.hpp | 112 + Netgen/libsrc/general/symbolta.cpp | 52 + Netgen/libsrc/general/symbolta.hpp | 158 + Netgen/libsrc/general/table.cpp | 192 + Netgen/libsrc/general/table.hpp | 202 + Netgen/libsrc/general/template.hpp | 422 ++ Netgen/libsrc/geom2d/Makefile | 12 + Netgen/libsrc/geom2d/genmesh2d.cpp | 121 + Netgen/libsrc/geom2d/geom2dmesh.cpp | 96 + Netgen/libsrc/geom2d/geom2dmesh.hpp | 38 + Netgen/libsrc/geom2d/geometry2d.hpp | 20 + Netgen/libsrc/geom2d/spline2d.cpp | 350 ++ Netgen/libsrc/geom2d/spline2d.hpp | 167 + Netgen/libsrc/geom2d/splinegeometry2.cpp | 224 ++ Netgen/libsrc/geom2d/splinegeometry2.hpp | 43 + Netgen/libsrc/gprim/Makefile | 14 + Netgen/libsrc/gprim/adtree.cpp | 2292 +++++++++++ Netgen/libsrc/gprim/adtree.hpp | 477 +++ Netgen/libsrc/gprim/geom2d.cpp | 485 +++ Netgen/libsrc/gprim/geom2d.hpp | 870 ++++ Netgen/libsrc/gprim/geom3d.cpp | 640 +++ Netgen/libsrc/gprim/geom3d.hpp | 728 ++++ Netgen/libsrc/gprim/geomfuncs.cpp | 111 + Netgen/libsrc/gprim/geomfuncs.hpp | 129 + Netgen/libsrc/gprim/geomobjects.hpp | 333 ++ Netgen/libsrc/gprim/geomobjects2.hpp | 366 ++ Netgen/libsrc/gprim/geomops.hpp | 374 ++ Netgen/libsrc/gprim/geomops2.hpp | 428 ++ Netgen/libsrc/gprim/geomtest3d.cpp | 1223 ++++++ Netgen/libsrc/gprim/geomtest3d.hpp | 80 + Netgen/libsrc/gprim/gprim.hpp | 26 + Netgen/libsrc/gprim/testgeom.cpp | 20 + Netgen/libsrc/gprim/transform3d.cpp | 172 + Netgen/libsrc/gprim/transform3d.hpp | 131 + Netgen/libsrc/include/csg.hpp | 1 + Netgen/libsrc/include/geometry2d.hpp | 1 + Netgen/libsrc/include/gprim.hpp | 1 + Netgen/libsrc/include/incvis.hpp | 33 + Netgen/libsrc/include/linalg.hpp | 1 + Netgen/libsrc/include/meshing.hpp | 1 + Netgen/libsrc/include/myadt.hpp | 1 + Netgen/libsrc/include/mydefs.hpp | 29 + Netgen/libsrc/include/occgeom.hpp | 1 + Netgen/libsrc/include/opti.hpp | 1 + Netgen/libsrc/include/stepgeom.hpp | 10 + Netgen/libsrc/include/stepreader.hpp | 1 + Netgen/libsrc/include/stlgeom.hpp | 1 + Netgen/libsrc/include/visual.hpp | 1 + Netgen/libsrc/interface/Makefile | 7 + Netgen/libsrc/interface/importsolution.cpp | 121 + Netgen/libsrc/interface/nginterface.cpp | 1301 ++++++ Netgen/libsrc/interface/nglib.cpp | 538 +++ Netgen/libsrc/interface/printdest.cpp | 11 + Netgen/libsrc/interface/readuser.cpp | 372 ++ Netgen/libsrc/interface/writeabaqus.cpp | 237 ++ Netgen/libsrc/interface/writediffpack.cpp | 296 ++ Netgen/libsrc/interface/writefeap.cpp | 220 ++ Netgen/libsrc/interface/writefluent.cpp | 200 + Netgen/libsrc/interface/writepermas.cpp | 169 + Netgen/libsrc/interface/writetecplot.cpp | 127 + Netgen/libsrc/interface/writetochnog.cpp | 108 + Netgen/libsrc/interface/writeuser.cpp | 729 ++++ Netgen/libsrc/interface/writeuser.hpp | 101 + Netgen/libsrc/interface/wuchemnitz.cpp | 309 ++ Netgen/libsrc/linalg/Makefile | 13 + Netgen/libsrc/linalg/basemat.cpp | 465 +++ Netgen/libsrc/linalg/basemat.hpp | 105 + Netgen/libsrc/linalg/densemat.cpp | 1443 +++++++ Netgen/libsrc/linalg/densemat.hpp | 260 ++ Netgen/libsrc/linalg/linalg.hpp | 33 + Netgen/libsrc/linalg/polynomial.cpp | 216 + Netgen/libsrc/linalg/polynomial.hpp | 45 + Netgen/libsrc/linalg/sparsmat.cpp | 1703 ++++++++ Netgen/libsrc/linalg/sparsmat.hpp | 261 ++ Netgen/libsrc/linalg/vector.cpp | 786 ++++ Netgen/libsrc/linalg/vector.hpp | 485 +++ Netgen/libsrc/makefile.inc | 46 + Netgen/libsrc/makefile.mach.INTEL | 18 + Netgen/libsrc/makefile.mach.LINUX | 20 + Netgen/libsrc/makefile.mach.SGI | 19 + Netgen/libsrc/makefile.mach.SGIGCC | 53 + Netgen/libsrc/makefile.mach.SUN | 16 + Netgen/libsrc/meshing/Makefile | 16 + Netgen/libsrc/meshing/adfront2.cpp | 535 +++ Netgen/libsrc/meshing/adfront2.hpp | 336 ++ Netgen/libsrc/meshing/adfront3.cpp | 895 +++++ Netgen/libsrc/meshing/adfront3.hpp | 274 ++ Netgen/libsrc/meshing/bisect.cpp | 2298 +++++++++++ Netgen/libsrc/meshing/bisect.hpp | 71 + Netgen/libsrc/meshing/boundarylayer.cpp | 91 + Netgen/libsrc/meshing/boundarylayer.hpp | 9 + Netgen/libsrc/meshing/clusters.cpp | 253 ++ Netgen/libsrc/meshing/clusters.hpp | 42 + Netgen/libsrc/meshing/curvedelems.cpp | 1910 +++++++++ Netgen/libsrc/meshing/curvedelems.hpp | 835 ++++ Netgen/libsrc/meshing/curvedelems2.cpp | 719 ++++ Netgen/libsrc/meshing/delaunay.cpp | 1652 ++++++++ Netgen/libsrc/meshing/findip.cpp | 115 + Netgen/libsrc/meshing/findip.hpp | 116 + Netgen/libsrc/meshing/geomsearch.cpp | 265 ++ Netgen/libsrc/meshing/geomsearch.hpp | 116 + Netgen/libsrc/meshing/global.cpp | 53 + Netgen/libsrc/meshing/global.hpp | 54 + Netgen/libsrc/meshing/hprefinement.cpp | 3703 +++++++++++++++++ Netgen/libsrc/meshing/hprefinement.hpp | 22 + Netgen/libsrc/meshing/improve2.cpp | 766 ++++ Netgen/libsrc/meshing/improve2.hpp | 91 + Netgen/libsrc/meshing/improve2gen.cpp | 465 +++ Netgen/libsrc/meshing/improve3.cpp | 1950 +++++++++ Netgen/libsrc/meshing/improve3.hpp | 50 + Netgen/libsrc/meshing/localh.cpp | 682 ++++ Netgen/libsrc/meshing/localh.hpp | 143 + Netgen/libsrc/meshing/meshclass.cpp | 4165 ++++++++++++++++++++ Netgen/libsrc/meshing/meshclass.hpp | 591 +++ Netgen/libsrc/meshing/meshfunc.cpp | 745 ++++ Netgen/libsrc/meshing/meshfunc.hpp | 42 + Netgen/libsrc/meshing/meshfunc2d.cpp | 61 + Netgen/libsrc/meshing/meshing.hpp | 48 + Netgen/libsrc/meshing/meshing2.cpp | 1650 ++++++++ Netgen/libsrc/meshing/meshing2.hpp | 149 + Netgen/libsrc/meshing/meshing3.cpp | 1303 ++++++ Netgen/libsrc/meshing/meshing3.hpp | 192 + Netgen/libsrc/meshing/meshtool.cpp | 865 ++++ Netgen/libsrc/meshing/meshtool.hpp | 82 + Netgen/libsrc/meshing/meshtype.cpp | 1880 +++++++++ Netgen/libsrc/meshing/meshtype.hpp | 919 +++++ Netgen/libsrc/meshing/msghandler.cpp | 186 + Netgen/libsrc/meshing/msghandler.hpp | 47 + Netgen/libsrc/meshing/netrule2.cpp | 212 + Netgen/libsrc/meshing/netrule3.cpp | 1143 ++++++ Netgen/libsrc/meshing/parser2.cpp | 550 +++ Netgen/libsrc/meshing/parser3.cpp | 987 +++++ Netgen/libsrc/meshing/prism2rls.cpp | 446 +++ Netgen/libsrc/meshing/pyramid2rls.cpp | 309 ++ Netgen/libsrc/meshing/pyramidrls.cpp | 263 ++ Netgen/libsrc/meshing/quadrls.cpp | 743 ++++ Netgen/libsrc/meshing/refine.cpp | 549 +++ Netgen/libsrc/meshing/ruler2.cpp | 642 +++ Netgen/libsrc/meshing/ruler2.hpp | 149 + Netgen/libsrc/meshing/ruler3.cpp | 1177 ++++++ Netgen/libsrc/meshing/ruler3.hpp | 210 + Netgen/libsrc/meshing/secondorder.cpp | 454 +++ Netgen/libsrc/meshing/smoothing2.cpp | 790 ++++ Netgen/libsrc/meshing/smoothing3.cpp | 1557 ++++++++ Netgen/libsrc/meshing/specials.cpp | 193 + Netgen/libsrc/meshing/specials.hpp | 16 + Netgen/libsrc/meshing/tetrarls.cpp | 1466 +++++++ Netgen/libsrc/meshing/topology.cpp | 1523 +++++++ Netgen/libsrc/meshing/topology.hpp | 109 + Netgen/libsrc/meshing/triarls.cpp | 468 +++ Netgen/libsrc/meshing/zrefine.cpp | 735 ++++ Netgen/libsrc/occ/Makefile | 11 + Netgen/libsrc/occ/occgenmesh.cpp | 666 ++++ Netgen/libsrc/occ/occgeom.cpp | 106 + Netgen/libsrc/occ/occgeom.hpp | 181 + Netgen/libsrc/occ/occmeshsurf.cpp | 387 ++ Netgen/libsrc/occ/occmeshsurf.hpp | 175 + Netgen/libsrc/opti/Makefile | 10 + Netgen/libsrc/opti/bfgs.cpp | 367 ++ Netgen/libsrc/opti/linopt.cpp | 73 + Netgen/libsrc/opti/linsearch.cpp | 346 ++ Netgen/libsrc/opti/opti.hpp | 142 + Netgen/libsrc/stlgeom/Makefile | 11 + Netgen/libsrc/stlgeom/meshstlsurface.cpp | 1118 ++++++ Netgen/libsrc/stlgeom/meshstlsurface.hpp | 120 + Netgen/libsrc/stlgeom/stlgeom.cpp | 3477 ++++++++++++++++ Netgen/libsrc/stlgeom/stlgeom.hpp | 450 +++ Netgen/libsrc/stlgeom/stlgeomchart.cpp | 801 ++++ Netgen/libsrc/stlgeom/stlgeommesh.cpp | 1591 ++++++++ Netgen/libsrc/stlgeom/stlline.cpp | 780 ++++ Netgen/libsrc/stlgeom/stlline.hpp | 188 + Netgen/libsrc/stlgeom/stltool.cpp | 1288 ++++++ Netgen/libsrc/stlgeom/stltool.hpp | 271 ++ Netgen/libsrc/stlgeom/stltopology.cpp | 1067 +++++ Netgen/libsrc/stlgeom/stltopology.hpp | 362 ++ Netgen/libsrc/visualization/Makefile | 13 + Netgen/libsrc/visualization/meshdoc.cpp | 615 +++ Netgen/libsrc/visualization/meshdoc.hpp | 37 + Netgen/libsrc/visualization/mvdraw.cpp | 1540 ++++++++ Netgen/libsrc/visualization/mvdraw.hpp | 352 ++ Netgen/libsrc/visualization/soldata.hpp | 41 + Netgen/libsrc/visualization/stlmeshing.cpp | 1080 +++++ Netgen/libsrc/visualization/visual.hpp | 26 + Netgen/libsrc/visualization/vscsg.cpp | 199 + Netgen/libsrc/visualization/vsmesh.cpp | 2741 +++++++++++++ Netgen/libsrc/visualization/vssolution.cpp | 2738 +++++++++++++ Netgen/libsrc/visualization/vssolution.hpp | 212 + configure | 59 + configure.in | 37 +- tutorial/t2.geo | 4 +- tutorial/t5.geo | 12 +- 281 files changed, 120140 insertions(+), 30 deletions(-) create mode 100644 Mesh/3D_Mesh_Netgen.cpp create mode 100644 Netgen/COPYING.LIB create mode 100644 Netgen/Makefile create mode 100644 Netgen/NEWS create mode 100644 Netgen/README.GMSH create mode 100644 Netgen/VERSION create mode 100644 Netgen/libsrc/Makefile create mode 100644 Netgen/libsrc/csg/Makefile create mode 100644 Netgen/libsrc/csg/algprim.cpp create mode 100644 Netgen/libsrc/csg/algprim.hpp create mode 100644 Netgen/libsrc/csg/brick.cpp create mode 100644 Netgen/libsrc/csg/brick.hpp create mode 100644 Netgen/libsrc/csg/bspline2d.cpp create mode 100644 Netgen/libsrc/csg/csg.hpp create mode 100644 Netgen/libsrc/csg/csgeom.cpp create mode 100644 Netgen/libsrc/csg/csgeom.hpp create mode 100644 Netgen/libsrc/csg/csgparser.cpp create mode 100644 Netgen/libsrc/csg/csgparser_dalibor.cpp create mode 100644 Netgen/libsrc/csg/csgscanner.cpp create mode 100644 Netgen/libsrc/csg/curve2d.cpp create mode 100644 Netgen/libsrc/csg/curve2d.hpp create mode 100644 Netgen/libsrc/csg/edgeflw.cpp create mode 100644 Netgen/libsrc/csg/edgeflw.hpp create mode 100644 Netgen/libsrc/csg/explicitcurve2d.cpp create mode 100644 Netgen/libsrc/csg/explicitcurve2d.hpp create mode 100644 Netgen/libsrc/csg/extrusion.cpp create mode 100644 Netgen/libsrc/csg/extrusion.hpp create mode 100644 Netgen/libsrc/csg/gencyl.cpp create mode 100644 Netgen/libsrc/csg/gencyl.hpp create mode 100644 Netgen/libsrc/csg/genmesh.cpp create mode 100644 Netgen/libsrc/csg/geometry.cpp create mode 100644 Netgen/libsrc/csg/geoml.hpp create mode 100644 Netgen/libsrc/csg/identify.cpp create mode 100644 Netgen/libsrc/csg/identify.hpp create mode 100644 Netgen/libsrc/csg/lex.yy.cpp create mode 100644 Netgen/libsrc/csg/manifold.cpp create mode 100644 Netgen/libsrc/csg/manifold.hpp create mode 100644 Netgen/libsrc/csg/meshsurf.cpp create mode 100644 Netgen/libsrc/csg/meshsurf.hpp create mode 100644 Netgen/libsrc/csg/polyhedra.cpp create mode 100644 Netgen/libsrc/csg/polyhedra.hpp create mode 100644 Netgen/libsrc/csg/revolution.cpp create mode 100644 Netgen/libsrc/csg/revolution.hpp create mode 100644 Netgen/libsrc/csg/singularref.cpp create mode 100644 Netgen/libsrc/csg/singularref.hpp create mode 100644 Netgen/libsrc/csg/solid.cpp create mode 100644 Netgen/libsrc/csg/solid.hpp create mode 100644 Netgen/libsrc/csg/specpoin.cpp create mode 100644 Netgen/libsrc/csg/specpoin.hpp create mode 100644 Netgen/libsrc/csg/spline3d.cpp create mode 100644 Netgen/libsrc/csg/spline3d.hpp create mode 100644 Netgen/libsrc/csg/surface.cpp create mode 100644 Netgen/libsrc/csg/surface.hpp create mode 100644 Netgen/libsrc/csg/triapprox.cpp create mode 100644 Netgen/libsrc/csg/triapprox.hpp create mode 100644 Netgen/libsrc/general/Makefile create mode 100644 Netgen/libsrc/general/array.cpp create mode 100644 Netgen/libsrc/general/array.hpp create mode 100644 Netgen/libsrc/general/autoptr.hpp create mode 100644 Netgen/libsrc/general/bitarray.cpp create mode 100644 Netgen/libsrc/general/bitarray.hpp create mode 100644 Netgen/libsrc/general/dynamicmem.cpp create mode 100644 Netgen/libsrc/general/dynamicmem.hpp create mode 100644 Netgen/libsrc/general/flags.cpp create mode 100644 Netgen/libsrc/general/flags.hpp create mode 100644 Netgen/libsrc/general/hashtabl.cpp create mode 100644 Netgen/libsrc/general/hashtabl.hpp create mode 100644 Netgen/libsrc/general/moveablemem.cpp create mode 100644 Netgen/libsrc/general/moveablemem.hpp create mode 100644 Netgen/libsrc/general/myadt.hpp create mode 100644 Netgen/libsrc/general/mystring.cpp create mode 100644 Netgen/libsrc/general/mystring.hpp create mode 100644 Netgen/libsrc/general/ngexception.cpp create mode 100644 Netgen/libsrc/general/ngexception.hpp create mode 100644 Netgen/libsrc/general/optmem.cpp create mode 100644 Netgen/libsrc/general/optmem.hpp create mode 100644 Netgen/libsrc/general/parthreads.cpp create mode 100644 Netgen/libsrc/general/parthreads.hpp create mode 100644 Netgen/libsrc/general/seti.cpp create mode 100644 Netgen/libsrc/general/seti.hpp create mode 100644 Netgen/libsrc/general/sort.cpp create mode 100644 Netgen/libsrc/general/sort.hpp create mode 100644 Netgen/libsrc/general/spbita2d.cpp create mode 100644 Netgen/libsrc/general/spbita2d.hpp create mode 100644 Netgen/libsrc/general/stack.hpp create mode 100644 Netgen/libsrc/general/symbolta.cpp create mode 100644 Netgen/libsrc/general/symbolta.hpp create mode 100644 Netgen/libsrc/general/table.cpp create mode 100644 Netgen/libsrc/general/table.hpp create mode 100644 Netgen/libsrc/general/template.hpp create mode 100644 Netgen/libsrc/geom2d/Makefile create mode 100644 Netgen/libsrc/geom2d/genmesh2d.cpp create mode 100644 Netgen/libsrc/geom2d/geom2dmesh.cpp create mode 100644 Netgen/libsrc/geom2d/geom2dmesh.hpp create mode 100644 Netgen/libsrc/geom2d/geometry2d.hpp create mode 100644 Netgen/libsrc/geom2d/spline2d.cpp create mode 100644 Netgen/libsrc/geom2d/spline2d.hpp create mode 100644 Netgen/libsrc/geom2d/splinegeometry2.cpp create mode 100644 Netgen/libsrc/geom2d/splinegeometry2.hpp create mode 100644 Netgen/libsrc/gprim/Makefile create mode 100644 Netgen/libsrc/gprim/adtree.cpp create mode 100644 Netgen/libsrc/gprim/adtree.hpp create mode 100644 Netgen/libsrc/gprim/geom2d.cpp create mode 100644 Netgen/libsrc/gprim/geom2d.hpp create mode 100644 Netgen/libsrc/gprim/geom3d.cpp create mode 100644 Netgen/libsrc/gprim/geom3d.hpp create mode 100644 Netgen/libsrc/gprim/geomfuncs.cpp create mode 100644 Netgen/libsrc/gprim/geomfuncs.hpp create mode 100644 Netgen/libsrc/gprim/geomobjects.hpp create mode 100644 Netgen/libsrc/gprim/geomobjects2.hpp create mode 100644 Netgen/libsrc/gprim/geomops.hpp create mode 100644 Netgen/libsrc/gprim/geomops2.hpp create mode 100644 Netgen/libsrc/gprim/geomtest3d.cpp create mode 100644 Netgen/libsrc/gprim/geomtest3d.hpp create mode 100644 Netgen/libsrc/gprim/gprim.hpp create mode 100644 Netgen/libsrc/gprim/testgeom.cpp create mode 100644 Netgen/libsrc/gprim/transform3d.cpp create mode 100644 Netgen/libsrc/gprim/transform3d.hpp create mode 100644 Netgen/libsrc/include/csg.hpp create mode 100644 Netgen/libsrc/include/geometry2d.hpp create mode 100644 Netgen/libsrc/include/gprim.hpp create mode 100644 Netgen/libsrc/include/incvis.hpp create mode 100644 Netgen/libsrc/include/linalg.hpp create mode 100644 Netgen/libsrc/include/meshing.hpp create mode 100644 Netgen/libsrc/include/myadt.hpp create mode 100644 Netgen/libsrc/include/mydefs.hpp create mode 100644 Netgen/libsrc/include/occgeom.hpp create mode 100644 Netgen/libsrc/include/opti.hpp create mode 100644 Netgen/libsrc/include/stepgeom.hpp create mode 100644 Netgen/libsrc/include/stepreader.hpp create mode 100644 Netgen/libsrc/include/stlgeom.hpp create mode 100644 Netgen/libsrc/include/visual.hpp create mode 100644 Netgen/libsrc/interface/Makefile create mode 100644 Netgen/libsrc/interface/importsolution.cpp create mode 100644 Netgen/libsrc/interface/nginterface.cpp create mode 100644 Netgen/libsrc/interface/nglib.cpp create mode 100644 Netgen/libsrc/interface/printdest.cpp create mode 100644 Netgen/libsrc/interface/readuser.cpp create mode 100644 Netgen/libsrc/interface/writeabaqus.cpp create mode 100644 Netgen/libsrc/interface/writediffpack.cpp create mode 100644 Netgen/libsrc/interface/writefeap.cpp create mode 100644 Netgen/libsrc/interface/writefluent.cpp create mode 100644 Netgen/libsrc/interface/writepermas.cpp create mode 100644 Netgen/libsrc/interface/writetecplot.cpp create mode 100644 Netgen/libsrc/interface/writetochnog.cpp create mode 100644 Netgen/libsrc/interface/writeuser.cpp create mode 100644 Netgen/libsrc/interface/writeuser.hpp create mode 100644 Netgen/libsrc/interface/wuchemnitz.cpp create mode 100644 Netgen/libsrc/linalg/Makefile create mode 100644 Netgen/libsrc/linalg/basemat.cpp create mode 100644 Netgen/libsrc/linalg/basemat.hpp create mode 100644 Netgen/libsrc/linalg/densemat.cpp create mode 100644 Netgen/libsrc/linalg/densemat.hpp create mode 100644 Netgen/libsrc/linalg/linalg.hpp create mode 100644 Netgen/libsrc/linalg/polynomial.cpp create mode 100644 Netgen/libsrc/linalg/polynomial.hpp create mode 100644 Netgen/libsrc/linalg/sparsmat.cpp create mode 100644 Netgen/libsrc/linalg/sparsmat.hpp create mode 100644 Netgen/libsrc/linalg/vector.cpp create mode 100644 Netgen/libsrc/linalg/vector.hpp create mode 100644 Netgen/libsrc/makefile.inc create mode 100644 Netgen/libsrc/makefile.mach.INTEL create mode 100644 Netgen/libsrc/makefile.mach.LINUX create mode 100644 Netgen/libsrc/makefile.mach.SGI create mode 100644 Netgen/libsrc/makefile.mach.SGIGCC create mode 100644 Netgen/libsrc/makefile.mach.SUN create mode 100644 Netgen/libsrc/meshing/Makefile create mode 100644 Netgen/libsrc/meshing/adfront2.cpp create mode 100644 Netgen/libsrc/meshing/adfront2.hpp create mode 100644 Netgen/libsrc/meshing/adfront3.cpp create mode 100644 Netgen/libsrc/meshing/adfront3.hpp create mode 100644 Netgen/libsrc/meshing/bisect.cpp create mode 100644 Netgen/libsrc/meshing/bisect.hpp create mode 100644 Netgen/libsrc/meshing/boundarylayer.cpp create mode 100644 Netgen/libsrc/meshing/boundarylayer.hpp create mode 100644 Netgen/libsrc/meshing/clusters.cpp create mode 100644 Netgen/libsrc/meshing/clusters.hpp create mode 100644 Netgen/libsrc/meshing/curvedelems.cpp create mode 100644 Netgen/libsrc/meshing/curvedelems.hpp create mode 100644 Netgen/libsrc/meshing/curvedelems2.cpp create mode 100644 Netgen/libsrc/meshing/delaunay.cpp create mode 100644 Netgen/libsrc/meshing/findip.cpp create mode 100644 Netgen/libsrc/meshing/findip.hpp create mode 100644 Netgen/libsrc/meshing/geomsearch.cpp create mode 100644 Netgen/libsrc/meshing/geomsearch.hpp create mode 100644 Netgen/libsrc/meshing/global.cpp create mode 100644 Netgen/libsrc/meshing/global.hpp create mode 100644 Netgen/libsrc/meshing/hprefinement.cpp create mode 100644 Netgen/libsrc/meshing/hprefinement.hpp create mode 100644 Netgen/libsrc/meshing/improve2.cpp create mode 100644 Netgen/libsrc/meshing/improve2.hpp create mode 100644 Netgen/libsrc/meshing/improve2gen.cpp create mode 100644 Netgen/libsrc/meshing/improve3.cpp create mode 100644 Netgen/libsrc/meshing/improve3.hpp create mode 100644 Netgen/libsrc/meshing/localh.cpp create mode 100644 Netgen/libsrc/meshing/localh.hpp create mode 100644 Netgen/libsrc/meshing/meshclass.cpp create mode 100644 Netgen/libsrc/meshing/meshclass.hpp create mode 100644 Netgen/libsrc/meshing/meshfunc.cpp create mode 100644 Netgen/libsrc/meshing/meshfunc.hpp create mode 100644 Netgen/libsrc/meshing/meshfunc2d.cpp create mode 100644 Netgen/libsrc/meshing/meshing.hpp create mode 100644 Netgen/libsrc/meshing/meshing2.cpp create mode 100644 Netgen/libsrc/meshing/meshing2.hpp create mode 100644 Netgen/libsrc/meshing/meshing3.cpp create mode 100644 Netgen/libsrc/meshing/meshing3.hpp create mode 100644 Netgen/libsrc/meshing/meshtool.cpp create mode 100644 Netgen/libsrc/meshing/meshtool.hpp create mode 100644 Netgen/libsrc/meshing/meshtype.cpp create mode 100644 Netgen/libsrc/meshing/meshtype.hpp create mode 100644 Netgen/libsrc/meshing/msghandler.cpp create mode 100644 Netgen/libsrc/meshing/msghandler.hpp create mode 100644 Netgen/libsrc/meshing/netrule2.cpp create mode 100644 Netgen/libsrc/meshing/netrule3.cpp create mode 100644 Netgen/libsrc/meshing/parser2.cpp create mode 100644 Netgen/libsrc/meshing/parser3.cpp create mode 100644 Netgen/libsrc/meshing/prism2rls.cpp create mode 100644 Netgen/libsrc/meshing/pyramid2rls.cpp create mode 100644 Netgen/libsrc/meshing/pyramidrls.cpp create mode 100644 Netgen/libsrc/meshing/quadrls.cpp create mode 100644 Netgen/libsrc/meshing/refine.cpp create mode 100644 Netgen/libsrc/meshing/ruler2.cpp create mode 100644 Netgen/libsrc/meshing/ruler2.hpp create mode 100644 Netgen/libsrc/meshing/ruler3.cpp create mode 100644 Netgen/libsrc/meshing/ruler3.hpp create mode 100644 Netgen/libsrc/meshing/secondorder.cpp create mode 100644 Netgen/libsrc/meshing/smoothing2.cpp create mode 100644 Netgen/libsrc/meshing/smoothing3.cpp create mode 100644 Netgen/libsrc/meshing/specials.cpp create mode 100644 Netgen/libsrc/meshing/specials.hpp create mode 100644 Netgen/libsrc/meshing/tetrarls.cpp create mode 100644 Netgen/libsrc/meshing/topology.cpp create mode 100644 Netgen/libsrc/meshing/topology.hpp create mode 100644 Netgen/libsrc/meshing/triarls.cpp create mode 100644 Netgen/libsrc/meshing/zrefine.cpp create mode 100644 Netgen/libsrc/occ/Makefile create mode 100644 Netgen/libsrc/occ/occgenmesh.cpp create mode 100644 Netgen/libsrc/occ/occgeom.cpp create mode 100644 Netgen/libsrc/occ/occgeom.hpp create mode 100644 Netgen/libsrc/occ/occmeshsurf.cpp create mode 100644 Netgen/libsrc/occ/occmeshsurf.hpp create mode 100644 Netgen/libsrc/opti/Makefile create mode 100644 Netgen/libsrc/opti/bfgs.cpp create mode 100644 Netgen/libsrc/opti/linopt.cpp create mode 100644 Netgen/libsrc/opti/linsearch.cpp create mode 100644 Netgen/libsrc/opti/opti.hpp create mode 100644 Netgen/libsrc/stlgeom/Makefile create mode 100644 Netgen/libsrc/stlgeom/meshstlsurface.cpp create mode 100644 Netgen/libsrc/stlgeom/meshstlsurface.hpp create mode 100644 Netgen/libsrc/stlgeom/stlgeom.cpp create mode 100644 Netgen/libsrc/stlgeom/stlgeom.hpp create mode 100644 Netgen/libsrc/stlgeom/stlgeomchart.cpp create mode 100644 Netgen/libsrc/stlgeom/stlgeommesh.cpp create mode 100644 Netgen/libsrc/stlgeom/stlline.cpp create mode 100644 Netgen/libsrc/stlgeom/stlline.hpp create mode 100644 Netgen/libsrc/stlgeom/stltool.cpp create mode 100644 Netgen/libsrc/stlgeom/stltool.hpp create mode 100644 Netgen/libsrc/stlgeom/stltopology.cpp create mode 100644 Netgen/libsrc/stlgeom/stltopology.hpp create mode 100644 Netgen/libsrc/visualization/Makefile create mode 100644 Netgen/libsrc/visualization/meshdoc.cpp create mode 100644 Netgen/libsrc/visualization/meshdoc.hpp create mode 100644 Netgen/libsrc/visualization/mvdraw.cpp create mode 100644 Netgen/libsrc/visualization/mvdraw.hpp create mode 100644 Netgen/libsrc/visualization/soldata.hpp create mode 100644 Netgen/libsrc/visualization/stlmeshing.cpp create mode 100644 Netgen/libsrc/visualization/visual.hpp create mode 100644 Netgen/libsrc/visualization/vscsg.cpp create mode 100644 Netgen/libsrc/visualization/vsmesh.cpp create mode 100644 Netgen/libsrc/visualization/vssolution.cpp create mode 100644 Netgen/libsrc/visualization/vssolution.hpp diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp index 45504626a2..68d229c245 100644 --- a/Common/CommandLine.cpp +++ b/Common/CommandLine.cpp @@ -1,4 +1,4 @@ -// $Id: CommandLine.cpp,v 1.43 2004-06-20 23:25:31 geuzaine Exp $ +// $Id: CommandLine.cpp,v 1.44 2004-06-26 17:58:14 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -46,8 +46,6 @@ extern Mesh *THEM; char *TheFileNameTab[MAX_OPEN_FILES]; char *TheBgmFileName = NULL, *TheOptString = NULL; -// *INDENT-OFF* - char gmsh_progname[] = "Gmsh, a 3D mesh generator with pre- and post-processing facilities" ; char gmsh_copyright[] = "Copyright (C) 1997-2004 Christophe Geuzaine and Jean-Francois Remacle"; char gmsh_version[] = "Version : " ; @@ -74,7 +72,7 @@ void Print_Usage(char *name){ Msg(DIRECT, " -saveall save all elements (discard physical group definitions)"); Msg(DIRECT, " -o file specify mesh output file name"); Msg(DIRECT, " -format msh|unv|gref set output mesh format (default: msh)"); - Msg(DIRECT, " -algo iso|tri|aniso select 2D mesh algorithm (default: iso)"); + Msg(DIRECT, " -algo iso|tri|aniso select mesh algorithm (default: iso)"); Msg(DIRECT, " -smooth int set mesh smoothing (default: 0)"); Msg(DIRECT, " -order int set mesh order (default: 1)"); Msg(DIRECT, " -scale float set global scaling factor (default: 1.0)"); @@ -125,6 +123,9 @@ char *Get_BuildOptions(void) #if defined(HAVE_TRIANGLE) strcat(opt, "TRIANGLE "); #endif +#if defined(HAVE_NETGEN) + strcat(opt, "NETGEN "); +#endif #if defined(HAVE_LIBJPEG) strcat(opt, "JPEG "); #endif @@ -142,8 +143,6 @@ char *Get_BuildOptions(void) return opt; } -// *INDENT-ON* - void Get_Options(int argc, char *argv[], int *nbfiles) { int i = 1; @@ -402,6 +401,8 @@ void Get_Options(int argc, char *argv[], int *nbfiles) CTX.mesh.algo2d = DELAUNAY_TRIANGLE; else if(!strncmp(argv[i], "aniso", 5)) CTX.mesh.algo2d = DELAUNAY_ANISO; + else if(!strncmp(argv[i], "netgen", 6)) + CTX.mesh.algo3d = FRONTAL_NETGEN; else { fprintf(stderr, ERROR_STR "Unknown mesh algorithm\n"); exit(1); diff --git a/Geo/GeoUtils.cpp b/Geo/GeoUtils.cpp index 81ce31524f..a7fc3e7095 100644 --- a/Geo/GeoUtils.cpp +++ b/Geo/GeoUtils.cpp @@ -1,4 +1,4 @@ -// $Id: GeoUtils.cpp,v 1.2 2004-06-26 05:07:47 geuzaine Exp $ +// $Id: GeoUtils.cpp,v 1.3 2004-06-26 17:58:14 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -140,7 +140,7 @@ void setVolumeSurfaces(Volume *v, List_T * loops) } else{ List_Add(v->Surfaces, &s); - int tmp = (s->Num > 0) ? 1 : -1; + int tmp = (is > 0) ? 1 : -1; List_Add(v->SurfacesOrientations, &tmp); } } diff --git a/Makefile b/Makefile index 7de1722010..373fa57e83 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.353 2004-06-20 23:30:36 geuzaine Exp $ +# $Id: Makefile,v 1.354 2004-06-26 17:58:14 geuzaine Exp $ # # Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle # @@ -146,7 +146,7 @@ source: source-common source-commercial: source-common cd gmsh-${GMSH_VERSION} && rm -rf CVS */CVS */*/CVS */*/*/CVS */.globalrc\ - MathEval Triangle/triangle.* TODO *.spec doc/gmsh.html doc/FAQ\ + MathEval Triangle/triangle.* Netgen/NGsrc TODO *.spec doc/gmsh.html doc/FAQ\ doc/README.cvs utils/commercial ${GMSH_VERSION_FILE} cp -f utils/commercial/README gmsh-${GMSH_VERSION}/README cp -f utils/commercial/LICENSE gmsh-${GMSH_VERSION}/doc/LICENSE diff --git a/Mesh/3D_Mesh.cpp b/Mesh/3D_Mesh.cpp index 75d0243c12..f9a6285b14 100644 --- a/Mesh/3D_Mesh.cpp +++ b/Mesh/3D_Mesh.cpp @@ -1,4 +1,4 @@ -// $Id: 3D_Mesh.cpp,v 1.60 2004-05-26 00:33:37 geuzaine Exp $ +// $Id: 3D_Mesh.cpp,v 1.61 2004-06-26 17:58:14 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -897,8 +897,12 @@ void Maillage_Volume(void *data, void *dum) } else if(MeshTransfiniteVolume(v)) { } - else if(v->Typ == 99999) { - + else if(v->Typ != 99999){ + if (Mesh_Netgen(v)) { + } + } + else if((v->Typ == 99999) && (CTX.mesh.algo3d !=FRONTAL_NETGEN)) { + Simplexes_New = List_Create(10, 10, sizeof(Simplex *)); Simplexes_Destroyed = List_Create(10, 10, sizeof(Simplex *)); @@ -910,6 +914,7 @@ void Maillage_Volume(void *data, void *dum) POINTS_LIST = List_Create(100, 100, sizeof(Vertex *)); LOCAL->Simplexes = v->Simplexes; LOCAL->Vertices = v->Vertices; + for(i = 0; i < List_Nbr(v->Surfaces); i++) { List_Read(v->Surfaces, i, &s); diff --git a/Mesh/3D_Mesh_Netgen.cpp b/Mesh/3D_Mesh_Netgen.cpp new file mode 100644 index 0000000000..1f8e851751 --- /dev/null +++ b/Mesh/3D_Mesh_Netgen.cpp @@ -0,0 +1,179 @@ +// $Id: 3D_Mesh_Netgen.cpp,v 1.1 2004-06-26 17:58:14 geuzaine Exp $ +// +// Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to <gmsh@geuz.org>. +// +// Contributor(s): +// Nicolas Tardieu +// + +#include "Gmsh.h" +#include "Mesh.h" +#include "Numeric.h" +#include "Context.h" + +#if !defined(HAVE_NETGEN) + +int Mesh_Netgen(Surface * s) +{ + Msg(GERROR, "Netgen is not compiled in this version of Gmsh"); + return 0; +} + +#else + +extern "C" +{ +#include "nglib.h" +} + +extern Context_T CTX; +extern Mesh *THEM; + +int Mesh_Netgen(Volume * v) +{ + if(CTX.mesh.algo3d != FRONTAL_NETGEN) + return 0; + + if(THEM->BGM.Typ == ONFILE){ + Msg(GERROR, "Netgen is not ready to be used with a background mesh"); + return 0; + } + + List_T *lSurfaceVertexList = List_Create(100, 100, sizeof(Vertex*)); + + // =================================== + // GMSH => NETGEN + // =================================== + + // creates Netgen mesh structure + Ng_Init(); + Ng_Mesh *lNetgenMesh = Ng_NewMesh(); + + // Transfert all surface vertices to Netgen + for(int i = 0; i < List_Nbr(v->Surfaces); i++) { + Surface *s; + List_Read(v->Surfaces, i, &s); + List_T *lVertexList = Tree2List(s->Vertices); + for(int j = 0; j < List_Nbr(lVertexList); j++) { + Vertex *lVertex; + List_Read(lVertexList, j, &lVertex); + // We must *not* add 2 times the same vertex (the same vertex + // can belong to several surfaces) + if(List_ISearchSeq(lSurfaceVertexList, &lVertex, compareVertex) < 0) { + List_Add(lSurfaceVertexList, &lVertex); + double tmp[3]; + tmp[0] = lVertex->Pos.X; + tmp[1] = lVertex->Pos.Y; + tmp[2] = lVertex->Pos.Z; + Ng_AddPoint(lNetgenMesh, tmp); + } + } + List_Delete(lVertexList) ; + } + + // Transfert all surface simplices to Netgen + for(int i = 0; i < List_Nbr(v->Surfaces); i++) { + Surface *s; + int sign; + List_Read(v->Surfaces, i, &s); + List_Read(v->SurfacesOrientations, i, &sign); + List_T *lSimplexeList = Tree2List(s->Simplexes); + for(int j = 0; j < List_Nbr(lSimplexeList); j++) { + Simplex *lSimplex; + List_Read(lSimplexeList, j, &lSimplex); + int tmp[3], index[3]; + if(sign > 0){ + index[0] = 0; + index[1] = 1; + index[2] = 2; + } + else{ + index[0] = 0; + index[1] = 2; + index[2] = 1; + } + tmp[0] = 1 + List_ISearchSeq(lSurfaceVertexList, &lSimplex->V[index[0]], + compareVertex); + tmp[1] = 1 + List_ISearchSeq(lSurfaceVertexList, &lSimplex->V[index[1]], + compareVertex); + tmp[2] = 1 + List_ISearchSeq(lSurfaceVertexList, &lSimplex->V[index[2]], + compareVertex); + Ng_AddSurfaceElement(lNetgenMesh, NG_TRIG, tmp); + } + List_Delete(lSimplexeList); + } + + // =================================== + // MESHING + // =================================== + + // define Netgen meshing option + Ng_Meshing_Parameters mp; + mp.maxh = 1; + mp.fineness = 1; + mp.secondorder = 0; + + // generate Netgen volume mesh + Msg(STATUS3, "Meshing volume %d", v->Num); + Ng_GenerateVolumeMesh(lNetgenMesh, &mp); + + // =================================== + // NETGEN => GMSH + // =================================== + + // Gets total number of vertices of Netgen's mesh + int lNbOfNGPoints = Ng_GetNP(lNetgenMesh); + Vertex **vtable = (Vertex **)Malloc(lNbOfNGPoints * sizeof(Vertex*)); + + // Writes existing surface vertices + for(int i = 0; i < List_Nbr(lSurfaceVertexList); i++) + List_Read(lSurfaceVertexList, i, &vtable[i]); + + // Writes and transfers new volume vertices + for(int i = List_Nbr(lSurfaceVertexList); i < lNbOfNGPoints; i++) { + double tmp[3]; + Ng_GetPoint(lNetgenMesh, i+1, tmp); + vtable[i] = Create_Vertex(++(THEM->MaxPointNum), tmp[0], tmp[1], tmp[2], 1., 0); + Tree_Add(v->Vertices, &vtable[i]); + Tree_Add(THEM->Vertices, &vtable[i]); + } + + // Get total number of simplices of Netgen's mesh + int lNbOfNGElements = Ng_GetNE(lNetgenMesh); + // Transfers new volume simplices + for(int i = 1; i <= lNbOfNGElements; i++) { + int tmp[4]; + Ng_GetVolumeElement(lNetgenMesh, i, tmp); + Simplex *lSimplex = Create_Simplex(vtable[tmp[0]-1], vtable[tmp[1]-1], + vtable[tmp[2]-1], vtable[tmp[3]-1]); + lSimplex->iEnt = v->Num; + Tree_Add(v->Simplexes, &lSimplex); + } + + List_Delete(lSurfaceVertexList); + Free(vtable); + + Ng_DeleteMesh(lNetgenMesh); + Ng_Exit(); + + return 1; +} + +#endif // !HAVE_NETGEN diff --git a/Mesh/Makefile b/Mesh/Makefile index c4a799bb1d..a6e305c2c8 100644 --- a/Mesh/Makefile +++ b/Mesh/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.65 2004-05-29 10:11:12 geuzaine Exp $ +# $Id: Makefile,v 1.66 2004-06-26 17:58:14 geuzaine Exp $ # # Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle # @@ -23,7 +23,8 @@ include ../variables LIB = ../lib/libGmshMesh.a INCLUDE = -I../Numeric -I../NR -I../Common -I../DataStr -I../Geo -I../Mesh\ - -I../Graphics -I../Parser -I../Fltk -I../Triangle + -I../Graphics -I../Parser -I../Fltk -I../Triangle\ + -I../Netgen/libsrc/include -I../Netgen/libsrc/interface CFLAGS = ${OPTIM} ${FLAGS} ${INCLUDE} SRC = 1D_Mesh.cpp \ @@ -51,6 +52,7 @@ SRC = 1D_Mesh.cpp \ 3D_Coherence.cpp \ 3D_Divide.cpp \ 3D_Bricks.cpp \ + 3D_Mesh_Netgen.cpp \ MeshQuality.cpp \ Create.cpp \ Generator.cpp \ @@ -84,7 +86,10 @@ ${LIB}: ${OBJ} # Don't optimize 3D_Mesh: it sometimes mysteriously crashes on Linux 3D_Mesh.o: - ${CXX} ${FLAGS} ${INCLUDE} -c $< + ${CXX} ${OPTIM} ${FLAGS} ${INCLUDE} -c $< + +3D_Mesh_Netgen.o: + ${CXX} ${OPTIM} ${FLAGS} ${INCLUDE} -c $< clean: rm -f *.o @@ -110,7 +115,7 @@ depend: ../Geo/CAD.h ../Mesh/Mesh.h ../Mesh/Vertex.h ../Mesh/Element.h \ ../Mesh/Simplex.h ../Mesh/Face.h ../Mesh/Edge.h ../Geo/ExtrudeParams.h \ ../Mesh/STL.h ../Common/VertexArray.h ../Mesh/Metric.h ../Mesh/Matrix.h \ - Utils.h Create.h 2D_Mesh.h ../Common/Context.h + Utils.h Create.h 2D_Mesh.h ../Common/Context.h Interpolation.h 2D_Transfinite.o: 2D_Transfinite.cpp ../Common/Gmsh.h ../Common/Message.h \ ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \ ../DataStr/avl.h ../DataStr/Tools.h ../Geo/Geo.h Mesh.h Vertex.h \ @@ -241,6 +246,11 @@ depend: ../DataStr/avl.h ../DataStr/Tools.h ../Numeric/Numeric.h Mesh.h \ Vertex.h Element.h Simplex.h Face.h Edge.h ../Geo/ExtrudeParams.h STL.h \ ../Common/VertexArray.h Metric.h Matrix.h +3D_Mesh_Netgen.o: 3D_Mesh_Netgen.cpp ../Common/Gmsh.h ../Common/Message.h \ + ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \ + ../DataStr/avl.h ../DataStr/Tools.h Mesh.h Vertex.h Element.h Simplex.h \ + Face.h Edge.h ../Geo/ExtrudeParams.h STL.h ../Common/VertexArray.h \ + Metric.h Matrix.h ../Numeric/Numeric.h ../Common/Context.h MeshQuality.o: MeshQuality.cpp ../Common/Gmsh.h ../Common/Message.h \ ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \ ../DataStr/avl.h ../DataStr/Tools.h ../Numeric/Numeric.h Mesh.h \ diff --git a/Mesh/Mesh.h b/Mesh/Mesh.h index 8ef09c18f0..c373ec234c 100644 --- a/Mesh/Mesh.h +++ b/Mesh/Mesh.h @@ -465,11 +465,12 @@ int MeshCylindricalSurface(Surface * s); int MeshParametricSurface(Surface * s); int MeshEllipticSurface(Surface * sur); -int AlgorithmeMaillage2DAnisotropeModeJF(Surface * s); +int AlgorithmeMaillage2DAnisotropeModeJF(Surface * s); void Maillage_Automatique_VieuxCode(Surface * pS, Mesh * m, int ori); -int Mesh_Shewchuk(Surface *s); +int Mesh_Shewchuk(Surface *s); +int Mesh_Netgen(Volume * v); -int Calcule_Contours(Surface * s); +int Calcule_Contours(Surface * s); void Link_Simplexes(List_T * Sim, Tree_T * Tim); void Calcule_Z(void *data, void *dum); void Calcule_Z_Plan(void *data, void *dum); @@ -482,7 +483,7 @@ void ReOrientSurfaceMesh(Surface *s); double Lc_XYZ(double X, double Y, double Z, Mesh * m); void ActionLiss(void *data, void *dummy); void ActionLissSurf(void *data, void *dummy); -int Recombine(Tree_T *TreeAllVert, Tree_T *TreeAllSimp, Tree_T *TreeAllQuad, +int Recombine(Tree_T *TreeAllVert, Tree_T *TreeAllSimp, Tree_T *TreeAllQuad, double a); void ApplyLcFactor(Mesh *M); void ExportLcFieldOnVolume(Mesh * M, char *filename); diff --git a/Netgen/COPYING.LIB b/Netgen/COPYING.LIB new file mode 100644 index 0000000000..b1e3f5a263 --- /dev/null +++ b/Netgen/COPYING.LIB @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/Netgen/Makefile b/Netgen/Makefile new file mode 100644 index 0000000000..d178bc3492 --- /dev/null +++ b/Netgen/Makefile @@ -0,0 +1,2926 @@ +# $Id: Makefile,v 1.1 2004-06-26 17:58:14 geuzaine Exp $ +# +# Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems to <gmsh@geuz.org>. + +include ../variables + +LIB = ../lib/libGmshNetgen.a +INCLUDE = -Ilibsrc/include +CFLAGS = ${OPTIM} ${INCLUDE} -DNO_PARALLEL_THREADS + +SRC = libsrc/opti/linopt.cpp \ + libsrc/opti/bfgs.cpp \ + libsrc/opti/linsearch.cpp \ + libsrc/meshing/global.cpp \ + libsrc/meshing/bisect.cpp \ + libsrc/meshing/meshtool.cpp \ + libsrc/meshing/refine.cpp \ + libsrc/meshing/ruler3.cpp \ + libsrc/meshing/improve3.cpp \ + libsrc/meshing/smoothing3.cpp \ + libsrc/meshing/adfront3.cpp \ + libsrc/meshing/tetrarls.cpp \ + libsrc/meshing/prism2rls.cpp \ + libsrc/meshing/pyramidrls.cpp \ + libsrc/meshing/pyramid2rls.cpp \ + libsrc/meshing/netrule3.cpp \ + libsrc/meshing/ruler2.cpp \ + libsrc/meshing/meshclass.cpp \ + libsrc/meshing/improve2.cpp \ + libsrc/meshing/smoothing2.cpp \ + libsrc/meshing/adfront2.cpp \ + libsrc/meshing/netrule2.cpp \ + libsrc/meshing/triarls.cpp \ + libsrc/meshing/geomsearch.cpp \ + libsrc/meshing/secondorder.cpp \ + libsrc/meshing/meshtype.cpp \ + libsrc/meshing/parser3.cpp \ + libsrc/meshing/meshing2.cpp \ + libsrc/meshing/quadrls.cpp \ + libsrc/meshing/specials.cpp \ + libsrc/meshing/parser2.cpp \ + libsrc/meshing/meshing3.cpp \ + libsrc/meshing/meshfunc.cpp \ + libsrc/meshing/localh.cpp \ + libsrc/meshing/improve2gen.cpp \ + libsrc/meshing/delaunay.cpp \ + libsrc/meshing/boundarylayer.cpp \ + libsrc/meshing/msghandler.cpp \ + libsrc/meshing/meshfunc2d.cpp \ + libsrc/meshing/topology.cpp \ + libsrc/meshing/clusters.cpp \ + libsrc/meshing/curvedelems.cpp \ + libsrc/meshing/curvedelems2.cpp \ + libsrc/interface/nglib.cpp \ + libsrc/gprim/geomtest3d.cpp \ + libsrc/gprim/geom2d.cpp \ + libsrc/gprim/geom3d.cpp \ + libsrc/gprim/adtree.cpp \ + libsrc/gprim/transform3d.cpp \ + libsrc/gprim/geomfuncs.cpp \ + libsrc/linalg/polynomial.cpp \ + libsrc/linalg/densemat.cpp \ + libsrc/linalg/vector.cpp \ + libsrc/csg/algprim.cpp \ + libsrc/csg/brick.cpp \ + libsrc/csg/manifold.cpp \ + libsrc/csg/bspline2d.cpp \ + libsrc/csg/meshsurf.cpp \ + libsrc/csg/csgeom.cpp \ + libsrc/csg/polyhedra.cpp \ + libsrc/csg/curve2d.cpp \ + libsrc/csg/singularref.cpp \ + libsrc/csg/edgeflw.cpp \ + libsrc/csg/solid.cpp \ + libsrc/csg/explicitcurve2d.cpp \ + libsrc/csg/specpoin.cpp \ + libsrc/csg/gencyl.cpp \ + libsrc/csg/revolution.cpp \ + libsrc/csg/genmesh.cpp \ + libsrc/csg/spline3d.cpp \ + libsrc/csg/surface.cpp \ + libsrc/csg/identify.cpp \ + libsrc/csg/triapprox.cpp \ + libsrc/geom2d/geom2dmesh.cpp \ + libsrc/geom2d/spline2d.cpp \ + libsrc/geom2d/splinegeometry2.cpp \ + libsrc/geom2d/genmesh2d.cpp \ + libsrc/stlgeom/meshstlsurface.cpp \ + libsrc/stlgeom/stlline.cpp \ + libsrc/stlgeom/stltopology.cpp \ + libsrc/stlgeom/stltool.cpp \ + libsrc/stlgeom/stlgeom.cpp \ + libsrc/stlgeom/stlgeomchart.cpp \ + libsrc/stlgeom/stlgeommesh.cpp \ + libsrc/general/moveablemem.cpp \ + libsrc/general/ngexception.cpp \ + libsrc/general/table.cpp \ + libsrc/general/optmem.cpp \ + libsrc/general/spbita2d.cpp \ + libsrc/general/hashtabl.cpp \ + libsrc/general/sort.cpp \ + libsrc/general/flags.cpp \ + libsrc/general/seti.cpp \ + libsrc/general/bitarray.cpp \ + libsrc/general/array.cpp \ + libsrc/general/symbolta.cpp \ + libsrc/general/mystring.cpp + +OBJ = ${SRC:.cpp=.o} + +.SUFFIXES: .o .cpp + +${LIB}: ${OBJ} + ${AR} ${LIB} ${OBJ} + ${RANLIB} ${LIB} + +.cpp.o: + ${CXX} ${CFLAGS} -c $< -o ${<:.cpp=.o} + +clean: + rm -f libsrc/*/*.o + +depend: + (sed '/^# DO NOT DELETE THIS LINE/q' Makefile && \ + ${CXX} -MM ${CFLAGS} ${SRC} \ + ) >Makefile.new + cp Makefile Makefile.bak + cp Makefile.new Makefile + rm -f Makefile.new + +# DO NOT DELETE THIS LINE +linopt.o: libsrc/opti/linopt.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/opti/opti.hpp +bfgs.o: libsrc/opti/bfgs.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/opti/opti.hpp +linsearch.o: libsrc/opti/linsearch.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/opti/opti.hpp +global.o: libsrc/meshing/global.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +bisect.o: libsrc/meshing/bisect.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp libsrc/interface/writeuser.hpp +meshtool.o: libsrc/meshing/meshtool.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp libsrc/include/csg.hpp libsrc/csg/csg.hpp \ + libsrc/include/meshing.hpp libsrc/csg/surface.hpp libsrc/csg/solid.hpp \ + libsrc/csg/identify.hpp libsrc/csg/singularref.hpp \ + libsrc/csg/csgeom.hpp libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp \ + libsrc/csg/brick.hpp libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp \ + libsrc/csg/curve2d.hpp libsrc/csg/explicitcurve2d.hpp \ + libsrc/csg/gencyl.hpp libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp \ + libsrc/include/geometry2d.hpp libsrc/geom2d/geometry2d.hpp \ + libsrc/geom2d/spline2d.hpp libsrc/geom2d/splinegeometry2.hpp \ + libsrc/geom2d/geom2dmesh.hpp +refine.o: libsrc/meshing/refine.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +ruler3.o: libsrc/meshing/ruler3.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +improve3.o: libsrc/meshing/improve3.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +smoothing3.o: libsrc/meshing/smoothing3.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +adfront3.o: libsrc/meshing/adfront3.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +tetrarls.o: libsrc/meshing/tetrarls.cpp +prism2rls.o: libsrc/meshing/prism2rls.cpp +pyramidrls.o: libsrc/meshing/pyramidrls.cpp +pyramid2rls.o: libsrc/meshing/pyramid2rls.cpp +netrule3.o: libsrc/meshing/netrule3.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +ruler2.o: libsrc/meshing/ruler2.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +meshclass.o: libsrc/meshing/meshclass.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +improve2.o: libsrc/meshing/improve2.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +smoothing2.o: libsrc/meshing/smoothing2.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +adfront2.o: libsrc/meshing/adfront2.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +netrule2.o: libsrc/meshing/netrule2.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +triarls.o: libsrc/meshing/triarls.cpp +geomsearch.o: libsrc/meshing/geomsearch.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +secondorder.o: libsrc/meshing/secondorder.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +meshtype.o: libsrc/meshing/meshtype.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +parser3.o: libsrc/meshing/parser3.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +meshing2.o: libsrc/meshing/meshing2.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +quadrls.o: libsrc/meshing/quadrls.cpp +specials.o: libsrc/meshing/specials.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +parser2.o: libsrc/meshing/parser2.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +meshing3.o: libsrc/meshing/meshing3.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +meshfunc.o: libsrc/meshing/meshfunc.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +localh.o: libsrc/meshing/localh.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +improve2gen.o: libsrc/meshing/improve2gen.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +delaunay.o: libsrc/meshing/delaunay.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +boundarylayer.o: libsrc/meshing/boundarylayer.cpp \ + libsrc/include/mystdlib.h libsrc/meshing/meshing.hpp \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp +msghandler.o: libsrc/meshing/msghandler.cpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mystdlib.h \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp +meshfunc2d.o: libsrc/meshing/meshfunc2d.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +topology.o: libsrc/meshing/topology.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +clusters.o: libsrc/meshing/clusters.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +curvedelems.o: libsrc/meshing/curvedelems.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +curvedelems2.o: libsrc/meshing/curvedelems2.cpp libsrc/include/mystdlib.h \ + libsrc/meshing/meshing.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp +nglib.o: libsrc/interface/nglib.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp \ + libsrc/include/stlgeom.hpp libsrc/stlgeom/stlgeom.hpp \ + libsrc/stlgeom/stltopology.hpp libsrc/stlgeom/stltool.hpp \ + libsrc/stlgeom/stlline.hpp libsrc/stlgeom/meshstlsurface.hpp \ + libsrc/include/geometry2d.hpp libsrc/geom2d/geometry2d.hpp \ + libsrc/geom2d/spline2d.hpp libsrc/geom2d/splinegeometry2.hpp \ + libsrc/geom2d/geom2dmesh.hpp libsrc/interface/nglib.h +geomtest3d.o: libsrc/gprim/geomtest3d.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp +geom2d.o: libsrc/gprim/geom2d.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp +geom3d.o: libsrc/gprim/geom3d.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp +adtree.o: libsrc/gprim/adtree.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp +transform3d.o: libsrc/gprim/transform3d.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp +geomfuncs.o: libsrc/gprim/geomfuncs.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp +polynomial.o: libsrc/linalg/polynomial.cpp libsrc/include/mystdlib.h \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp +densemat.o: libsrc/linalg/densemat.cpp libsrc/include/mystdlib.h \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp +vector.o: libsrc/linalg/vector.cpp +algprim.o: libsrc/csg/algprim.cpp libsrc/include/mystdlib.h \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +brick.o: libsrc/csg/brick.cpp libsrc/include/mystdlib.h \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +manifold.o: libsrc/csg/manifold.cpp libsrc/include/csg.hpp \ + libsrc/csg/csg.hpp libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mystdlib.h libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp libsrc/csg/surface.hpp libsrc/csg/solid.hpp \ + libsrc/csg/identify.hpp libsrc/csg/singularref.hpp \ + libsrc/csg/csgeom.hpp libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp \ + libsrc/csg/brick.hpp libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp \ + libsrc/csg/curve2d.hpp libsrc/csg/explicitcurve2d.hpp \ + libsrc/csg/gencyl.hpp libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +bspline2d.o: libsrc/csg/bspline2d.cpp libsrc/include/mystdlib.h \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp libsrc/csg/surface.hpp libsrc/csg/solid.hpp \ + libsrc/csg/identify.hpp libsrc/csg/singularref.hpp \ + libsrc/csg/csgeom.hpp libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp \ + libsrc/csg/brick.hpp libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp \ + libsrc/csg/curve2d.hpp libsrc/csg/explicitcurve2d.hpp \ + libsrc/csg/gencyl.hpp libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +meshsurf.o: libsrc/csg/meshsurf.cpp libsrc/include/mystdlib.h \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp libsrc/csg/surface.hpp libsrc/csg/solid.hpp \ + libsrc/csg/identify.hpp libsrc/csg/singularref.hpp \ + libsrc/csg/csgeom.hpp libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp \ + libsrc/csg/brick.hpp libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp \ + libsrc/csg/curve2d.hpp libsrc/csg/explicitcurve2d.hpp \ + libsrc/csg/gencyl.hpp libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +csgeom.o: libsrc/csg/csgeom.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +polyhedra.o: libsrc/csg/polyhedra.cpp libsrc/include/mystdlib.h \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +curve2d.o: libsrc/csg/curve2d.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/csg.hpp libsrc/csg/csg.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp libsrc/csg/surface.hpp libsrc/csg/solid.hpp \ + libsrc/csg/identify.hpp libsrc/csg/singularref.hpp \ + libsrc/csg/csgeom.hpp libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp \ + libsrc/csg/brick.hpp libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp \ + libsrc/csg/curve2d.hpp libsrc/csg/explicitcurve2d.hpp \ + libsrc/csg/gencyl.hpp libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +singularref.o: libsrc/csg/singularref.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +edgeflw.o: libsrc/csg/edgeflw.cpp libsrc/include/mystdlib.h \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/csg/surface.hpp \ + libsrc/csg/solid.hpp libsrc/csg/identify.hpp libsrc/csg/singularref.hpp \ + libsrc/csg/csgeom.hpp libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp \ + libsrc/csg/brick.hpp libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp \ + libsrc/csg/curve2d.hpp libsrc/csg/explicitcurve2d.hpp \ + libsrc/csg/gencyl.hpp libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +solid.o: libsrc/csg/solid.cpp libsrc/include/mystdlib.h \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +explicitcurve2d.o: libsrc/csg/explicitcurve2d.cpp \ + libsrc/include/mystdlib.h libsrc/include/csg.hpp libsrc/csg/csg.hpp \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +specpoin.o: libsrc/csg/specpoin.cpp libsrc/include/mystdlib.h \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/csg/surface.hpp \ + libsrc/csg/solid.hpp libsrc/csg/identify.hpp libsrc/csg/singularref.hpp \ + libsrc/csg/csgeom.hpp libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp \ + libsrc/csg/brick.hpp libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp \ + libsrc/csg/curve2d.hpp libsrc/csg/explicitcurve2d.hpp \ + libsrc/csg/gencyl.hpp libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +gencyl.o: libsrc/csg/gencyl.cpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mystdlib.h \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +revolution.o: libsrc/csg/revolution.cpp libsrc/include/mystdlib.h \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +genmesh.o: libsrc/csg/genmesh.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp \ + libsrc/include/stlgeom.hpp libsrc/stlgeom/stlgeom.hpp \ + libsrc/stlgeom/stltopology.hpp libsrc/stlgeom/stltool.hpp \ + libsrc/stlgeom/stlline.hpp libsrc/stlgeom/meshstlsurface.hpp +spline3d.o: libsrc/csg/spline3d.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +surface.o: libsrc/csg/surface.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/csg.hpp libsrc/csg/csg.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp libsrc/csg/surface.hpp libsrc/csg/solid.hpp \ + libsrc/csg/identify.hpp libsrc/csg/singularref.hpp \ + libsrc/csg/csgeom.hpp libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp \ + libsrc/csg/brick.hpp libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp \ + libsrc/csg/curve2d.hpp libsrc/csg/explicitcurve2d.hpp \ + libsrc/csg/gencyl.hpp libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +identify.o: libsrc/csg/identify.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +triapprox.o: libsrc/csg/triapprox.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp +geom2dmesh.o: libsrc/geom2d/geom2dmesh.cpp libsrc/include/mystdlib.h \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp libsrc/csg/surface.hpp libsrc/csg/solid.hpp \ + libsrc/csg/identify.hpp libsrc/csg/singularref.hpp \ + libsrc/csg/csgeom.hpp libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp \ + libsrc/csg/brick.hpp libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp \ + libsrc/csg/curve2d.hpp libsrc/csg/explicitcurve2d.hpp \ + libsrc/csg/gencyl.hpp libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp \ + libsrc/include/geometry2d.hpp libsrc/geom2d/geometry2d.hpp \ + libsrc/geom2d/spline2d.hpp libsrc/geom2d/splinegeometry2.hpp \ + libsrc/geom2d/geom2dmesh.hpp +spline2d.o: libsrc/geom2d/spline2d.cpp libsrc/include/mystdlib.h \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp libsrc/csg/surface.hpp libsrc/csg/solid.hpp \ + libsrc/csg/identify.hpp libsrc/csg/singularref.hpp \ + libsrc/csg/csgeom.hpp libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp \ + libsrc/csg/brick.hpp libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp \ + libsrc/csg/curve2d.hpp libsrc/csg/explicitcurve2d.hpp \ + libsrc/csg/gencyl.hpp libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp \ + libsrc/geom2d/spline2d.hpp +splinegeometry2.o: libsrc/geom2d/splinegeometry2.cpp \ + libsrc/include/mystdlib.h libsrc/include/csg.hpp libsrc/csg/csg.hpp \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/csg/surface.hpp libsrc/csg/solid.hpp libsrc/csg/identify.hpp \ + libsrc/csg/singularref.hpp libsrc/csg/csgeom.hpp \ + libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp libsrc/csg/brick.hpp \ + libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp libsrc/csg/curve2d.hpp \ + libsrc/csg/explicitcurve2d.hpp libsrc/csg/gencyl.hpp \ + libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp \ + libsrc/geom2d/spline2d.hpp libsrc/geom2d/splinegeometry2.hpp +genmesh2d.o: libsrc/geom2d/genmesh2d.cpp libsrc/include/mystdlib.h \ + libsrc/include/csg.hpp libsrc/csg/csg.hpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/opti.hpp \ + libsrc/opti/opti.hpp libsrc/meshing/msghandler.hpp \ + libsrc/meshing/meshtype.hpp libsrc/meshing/localh.hpp \ + libsrc/meshing/meshclass.hpp libsrc/meshing/global.hpp \ + libsrc/meshing/meshtool.hpp libsrc/meshing/ruler2.hpp \ + libsrc/meshing/adfront2.hpp libsrc/meshing/meshing2.hpp \ + libsrc/meshing/improve2.hpp libsrc/meshing/geomsearch.hpp \ + libsrc/meshing/adfront3.hpp libsrc/meshing/ruler3.hpp \ + libsrc/meshing/meshing3.hpp libsrc/meshing/improve3.hpp \ + libsrc/meshing/findip.hpp libsrc/meshing/topology.hpp \ + libsrc/meshing/curvedelems.hpp libsrc/meshing/bisect.hpp \ + libsrc/meshing/clusters.hpp libsrc/meshing/meshfunc.hpp \ + libsrc/meshing/hprefinement.hpp libsrc/meshing/boundarylayer.hpp \ + libsrc/meshing/specials.hpp libsrc/csg/surface.hpp libsrc/csg/solid.hpp \ + libsrc/csg/identify.hpp libsrc/csg/singularref.hpp \ + libsrc/csg/csgeom.hpp libsrc/csg/triapprox.hpp libsrc/csg/algprim.hpp \ + libsrc/csg/brick.hpp libsrc/csg/spline3d.hpp libsrc/csg/manifold.hpp \ + libsrc/csg/curve2d.hpp libsrc/csg/explicitcurve2d.hpp \ + libsrc/csg/gencyl.hpp libsrc/csg/polyhedra.hpp libsrc/csg/extrusion.hpp \ + libsrc/csg/revolution.hpp libsrc/csg/specpoin.hpp \ + libsrc/csg/edgeflw.hpp libsrc/csg/meshsurf.hpp \ + libsrc/include/geometry2d.hpp libsrc/geom2d/geometry2d.hpp \ + libsrc/geom2d/spline2d.hpp libsrc/geom2d/splinegeometry2.hpp \ + libsrc/geom2d/geom2dmesh.hpp +meshstlsurface.o: libsrc/stlgeom/meshstlsurface.cpp \ + libsrc/include/mystdlib.h libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mydefs.hpp \ + libsrc/general/ngexception.hpp libsrc/general/parthreads.hpp \ + libsrc/general/moveablemem.hpp libsrc/general/dynamicmem.hpp \ + libsrc/general/template.hpp libsrc/general/array.hpp \ + libsrc/general/table.hpp libsrc/general/hashtabl.hpp \ + libsrc/general/symbolta.hpp libsrc/general/bitarray.hpp \ + libsrc/general/flags.hpp libsrc/general/spbita2d.hpp \ + libsrc/general/seti.hpp libsrc/general/optmem.hpp \ + libsrc/general/autoptr.hpp libsrc/general/sort.hpp \ + libsrc/general/stack.hpp libsrc/general/mystring.hpp \ + libsrc/include/linalg.hpp libsrc/linalg/linalg.hpp \ + libsrc/linalg/vector.hpp libsrc/linalg/densemat.hpp \ + libsrc/linalg/polynomial.hpp libsrc/include/gprim.hpp \ + libsrc/gprim/gprim.hpp libsrc/gprim/geomobjects.hpp \ + libsrc/gprim/geomops.hpp libsrc/gprim/geomfuncs.hpp \ + libsrc/gprim/geom2d.hpp libsrc/gprim/geom3d.hpp \ + libsrc/gprim/geomtest3d.hpp libsrc/gprim/transform3d.hpp \ + libsrc/gprim/adtree.hpp libsrc/include/meshing.hpp \ + libsrc/meshing/meshing.hpp libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/stlgeom/stlgeom.hpp libsrc/stlgeom/stltopology.hpp \ + libsrc/stlgeom/stltool.hpp libsrc/stlgeom/stlline.hpp \ + libsrc/stlgeom/meshstlsurface.hpp +stlline.o: libsrc/stlgeom/stlline.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/stlgeom/stlgeom.hpp libsrc/stlgeom/stltopology.hpp \ + libsrc/stlgeom/stltool.hpp libsrc/stlgeom/stlline.hpp \ + libsrc/stlgeom/meshstlsurface.hpp +stltopology.o: libsrc/stlgeom/stltopology.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/stlgeom/stlgeom.hpp libsrc/stlgeom/stltopology.hpp \ + libsrc/stlgeom/stltool.hpp libsrc/stlgeom/stlline.hpp \ + libsrc/stlgeom/meshstlsurface.hpp +stltool.o: libsrc/stlgeom/stltool.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/stlgeom/stlgeom.hpp libsrc/stlgeom/stltopology.hpp \ + libsrc/stlgeom/stltool.hpp libsrc/stlgeom/stlline.hpp \ + libsrc/stlgeom/meshstlsurface.hpp +stlgeom.o: libsrc/stlgeom/stlgeom.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/stlgeom/stlgeom.hpp libsrc/stlgeom/stltopology.hpp \ + libsrc/stlgeom/stltool.hpp libsrc/stlgeom/stlline.hpp \ + libsrc/stlgeom/meshstlsurface.hpp +stlgeomchart.o: libsrc/stlgeom/stlgeomchart.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/stlgeom/stlgeom.hpp libsrc/stlgeom/stltopology.hpp \ + libsrc/stlgeom/stltool.hpp libsrc/stlgeom/stlline.hpp \ + libsrc/stlgeom/meshstlsurface.hpp +stlgeommesh.o: libsrc/stlgeom/stlgeommesh.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp \ + libsrc/include/meshing.hpp libsrc/meshing/meshing.hpp \ + libsrc/include/opti.hpp libsrc/opti/opti.hpp \ + libsrc/meshing/msghandler.hpp libsrc/meshing/meshtype.hpp \ + libsrc/meshing/localh.hpp libsrc/meshing/meshclass.hpp \ + libsrc/meshing/global.hpp libsrc/meshing/meshtool.hpp \ + libsrc/meshing/ruler2.hpp libsrc/meshing/adfront2.hpp \ + libsrc/meshing/meshing2.hpp libsrc/meshing/improve2.hpp \ + libsrc/meshing/geomsearch.hpp libsrc/meshing/adfront3.hpp \ + libsrc/meshing/ruler3.hpp libsrc/meshing/meshing3.hpp \ + libsrc/meshing/improve3.hpp libsrc/meshing/findip.hpp \ + libsrc/meshing/topology.hpp libsrc/meshing/curvedelems.hpp \ + libsrc/meshing/bisect.hpp libsrc/meshing/clusters.hpp \ + libsrc/meshing/meshfunc.hpp libsrc/meshing/hprefinement.hpp \ + libsrc/meshing/boundarylayer.hpp libsrc/meshing/specials.hpp \ + libsrc/stlgeom/stlgeom.hpp libsrc/stlgeom/stltopology.hpp \ + libsrc/stlgeom/stltool.hpp libsrc/stlgeom/stlline.hpp \ + libsrc/stlgeom/meshstlsurface.hpp +moveablemem.o: libsrc/general/moveablemem.cpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mystdlib.h \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp +ngexception.o: libsrc/general/ngexception.cpp libsrc/include/myadt.hpp \ + libsrc/general/myadt.hpp libsrc/include/mystdlib.h \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp +table.o: libsrc/general/table.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp +optmem.o: libsrc/general/optmem.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp +spbita2d.o: libsrc/general/spbita2d.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp +hashtabl.o: libsrc/general/hashtabl.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp +sort.o: libsrc/general/sort.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp +flags.o: libsrc/general/flags.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp +seti.o: libsrc/general/seti.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp +bitarray.o: libsrc/general/bitarray.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp +array.o: libsrc/general/array.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp +symbolta.o: libsrc/general/symbolta.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp +mystring.o: libsrc/general/mystring.cpp libsrc/include/mystdlib.h \ + libsrc/include/myadt.hpp libsrc/general/myadt.hpp \ + libsrc/include/mydefs.hpp libsrc/general/ngexception.hpp \ + libsrc/general/parthreads.hpp libsrc/general/moveablemem.hpp \ + libsrc/general/dynamicmem.hpp libsrc/general/template.hpp \ + libsrc/general/array.hpp libsrc/general/table.hpp \ + libsrc/general/hashtabl.hpp libsrc/general/symbolta.hpp \ + libsrc/general/bitarray.hpp libsrc/general/flags.hpp \ + libsrc/general/spbita2d.hpp libsrc/general/seti.hpp \ + libsrc/general/optmem.hpp libsrc/general/autoptr.hpp \ + libsrc/general/sort.hpp libsrc/general/stack.hpp \ + libsrc/general/mystring.hpp libsrc/include/linalg.hpp \ + libsrc/linalg/linalg.hpp libsrc/linalg/vector.hpp \ + libsrc/linalg/densemat.hpp libsrc/linalg/polynomial.hpp \ + libsrc/include/gprim.hpp libsrc/gprim/gprim.hpp \ + libsrc/gprim/geomobjects.hpp libsrc/gprim/geomops.hpp \ + libsrc/gprim/geomfuncs.hpp libsrc/gprim/geom2d.hpp \ + libsrc/gprim/geom3d.hpp libsrc/gprim/geomtest3d.hpp \ + libsrc/gprim/transform3d.hpp libsrc/gprim/adtree.hpp diff --git a/Netgen/NEWS b/Netgen/NEWS new file mode 100644 index 0000000000..76efa8384b --- /dev/null +++ b/Netgen/NEWS @@ -0,0 +1,9 @@ +New features and improvements in NG4.3: + +- support for high order curved elements +- new, hand written CSG parser +- CSG primitives 'ellipticcylinder' and 'ellipsoid' +- improvements for Delaunay meshing +- improvements in surface optimization +- mesh interface with full topology (element-face-edge-vertex) + diff --git a/Netgen/README.GMSH b/Netgen/README.GMSH new file mode 100644 index 0000000000..bfc68ef9f0 --- /dev/null +++ b/Netgen/README.GMSH @@ -0,0 +1,69 @@ + +This directory may contain a modified version of Joachim Schoberl's +NETGEN mesh generator: + +- only the libsrc directory was kept from the original distribution +- the file meshing/improve2d.cpp was slightly modified + +**IMPORTANT NOTICE** + +Netgen requires the boundary mesh to be oriented with exterior +pointing normals. You HAVE TO define your geometry so that this +criterion is fulfilled (i.e., correctly orient the geometry surfaces +and the surface loops). Failing to do so will result in NETGEN to +fail (and exit). + +************************************************************** + +From NETGEN's documentation: + +What is NETGEN +============== + +NETGEN is an automatic mesh generation tool for two and three +dimensions. Netgen is open source under the conditions of the LGPL. +It comes as stand alone programme with graphical user +interface, or as C++ library to be linked into an other application. +Netgen is available for Unix/Linux and Windows 98/NT. Netgen +generates triangular or quadrilateral meshes in 2D, and tetrahedral +meshes in 3D. The input for 2D is described by spline curves, and the +input for 3D problems is either defined by constructive solid +geometries (CSG), see Chapter \ref{chap_csg}, or by the standard STL +file format. NETGEN contains modules for mesh optimization and +hierarchical mesh refinement. Curved elements are supported of arbitrary +order. + +The history of NETGEN +===================== + +The NETGEN project was started 1994 in the master's programme of +Joachim Sch\"oberl, under supervision of Prof. Ulrich Langer, at the +Department of Computational Mathematics and Optimization, University +Linz, Austria. Its further development was supported by the Austrian +science Fund ``Fonds zur F\"orderung der wissenschaftlichen +Forschung'' (http://www.fwf.ac.at) under projects P 10643-TEC and SFB +1306. The current home of Netgen is the Start project ``hp-FEM'' +(http://www.hpfem.jku.at) granted by the FWF. + +Special thanks go to +- Robert Gaisbauer: High order curved elements +- Hannes Gerstmayr: Meshing of STL geometry + +How to receive NETGEN +===================== + +NETGEN is available from the WEB at http://www.hpfem.jku.at/netgen +You find there source code releases for Linux/Unix/Windows, as well +as compiled versions for Windows. You can use CVS access to receive +the most up to date version. + +************************************************************** + +From NETGEN's README.install file: + +Latest information is available from: +http://www.sfb013.uni-linz.ac.at/~joachim/netgen + +People might have asked similar questions on +https://www.sfb013.uni-linz.ac.at/mailman/listinfo/netgen +(please note the s in https) diff --git a/Netgen/VERSION b/Netgen/VERSION new file mode 100644 index 0000000000..74c0c9cbcc --- /dev/null +++ b/Netgen/VERSION @@ -0,0 +1 @@ +NG Version 4.3.1 \ No newline at end of file diff --git a/Netgen/libsrc/Makefile b/Netgen/libsrc/Makefile new file mode 100644 index 0000000000..4bf820bc2a --- /dev/null +++ b/Netgen/libsrc/Makefile @@ -0,0 +1,38 @@ +# +# +appl = NETGEN +.default all: +# +# +all: + @ (cd linalg; $(MAKE) -f Makefile) + @ (cd general; $(MAKE) -f Makefile) + @ (cd gprim; $(MAKE) -f Makefile) + @ (cd csg; $(MAKE) -f Makefile) + @ (cd geom2d; $(MAKE) -f Makefile) + @ (cd stlgeom; $(MAKE) -f Makefile) + @ (cd occ; $(MAKE) -f Makefile) + @ (cd meshing; $(MAKE) -f Makefile) + @ (cd opti; $(MAKE) -f Makefile) + @ (cd visualization; $(MAKE) -f Makefile) + @ (cd interface; $(MAKE) -f Makefile) +# +# @ (cd step; $(MAKE) -f Makefile) +# @ (cd stepgeom; $(MAKE) -f Makefile) +# @ (cd graphics; $(MAKE) -f Makefile) + +tar: + tar cvf ../../libsrc.tar Makefile + tar rf ../../libsrc.tar linalg/Makefile linalg/*.hh linalg/*.cc + tar rf ../../libsrc.tar general/Makefile general/*.hh general/*.cc + tar rf ../../libsrc.tar gprim/Makefile gprim/*.hh gprim/*.cc + tar rf ../../libsrc.tar csg/Makefile csg/*.hh csg/*.cc + tar rf ../../libsrc.tar stlgeom/Makefile stlgeom/*.hh stlgeom/*.cc + tar rf ../../libsrc.tar occ/Makefile occ/*.h* occ/*.c* + tar rf ../../libsrc.tar meshing/Makefile meshing/*.hh meshing/*.cc meshing/*.h + tar rf ../../libsrc.tar opti/Makefile opti/*.hh opti/*.cc + tar rf ../../libsrc.tar step/Makefile step/*.h step/*.cc + tar rf ../../libsrc.tar stepgeom/Makefile stepgeom/*.hh stepgeom/*.cc + tar tf ../../libsrc.tar include/*.h include/*.hh + gzip -9 ../../libsrc.tar + diff --git a/Netgen/libsrc/csg/Makefile b/Netgen/libsrc/csg/Makefile new file mode 100644 index 0000000000..e8c51dc218 --- /dev/null +++ b/Netgen/libsrc/csg/Makefile @@ -0,0 +1,26 @@ +# +# Makefile for geometric library +# +src = csgparser.cpp algprim.cpp curve2d.cpp brick.cpp \ + solid.cpp spline3d.cpp surface.cpp bspline2d.cpp \ + explicitcurve2d.cpp gencyl.cpp csgeom.cpp polyhedra.cpp extrusion.cpp revolution.cpp \ + manifold.cpp curve2d.cpp triapprox.cpp identify.cpp \ + singularref.cpp \ + edgeflw.cpp specpoin.cpp meshsurf.cpp genmesh.cpp +# +# lex.yy.cpp geometry.cpp +# +lib = csg +libpath = libsrc/csg +# +# +include ../makefile.inc +# +# geometry.cpp : geometry.yy +# bison -d -o geometry.c geometry.yy +# mv -f geometry.c geometry.cpp +# +# lex.yy.cpp : geometry.yy geometry.ll +# flex -+ -d -I geometry.ll +# mv lex.yy.cc lex.yy.cpp + diff --git a/Netgen/libsrc/csg/algprim.cpp b/Netgen/libsrc/csg/algprim.cpp new file mode 100644 index 0000000000..756e4bd1af --- /dev/null +++ b/Netgen/libsrc/csg/algprim.cpp @@ -0,0 +1,1371 @@ +#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 << endl; +} + + +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) +{ + p = ap; + n = an; + 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; + + 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)); +} + + + +void Plane :: GetPrimitiveData (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); + + 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 :: 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 +{ + 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; + GetNormalVector (p, n1); + s2.GetNormalVector (p, n2); + 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 +{ + /* + Vec<3> p1p; + Point<2> pplane2 = pplane; + + pplane2 *= h; + p1p = pplane2(0) * ex + pplane2(1) * ey; + p3d = p1 + p1p; + */ + p3d = p1 + (h * pplane(0)) * ex + (h * pplane(1)) * ey; +} + + +void Plane :: Project (Point<3> & p3d) const +{ + double val = CalcFunctionValue (p3d); + p3d -= val * n; +} + +INSOLID_TYPE Plane :: BoxInSolid (const BoxSphere<3> & box) const +{ + int i; + double val; + Point<3> p; + + val = 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++) + { + p = box.GetPointNr (i); + val = CalcFunctionValue (p); + 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++) + { + p = box.GetPointNr (i); + val = CalcFunctionValue (p); + 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; + + 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 (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); + + 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; +} + + + + +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 i, j; + double lg, bg; + int n = int(facets) + 1; + + for (j = 0; j <= n; j++) + for (i = 0; i <= n; i++) + { + lg = 2 * M_PI * double (i) / n; + 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 (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)); + } +} + + + + + +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; + + cout << "orhtogonal ? " << (v1*v2) << ", " << (v1*v3) << ", " << (v2*v3) << endl; + 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) lv1 = 1; + double lv2 = v2.Length2 (); + if (!lv2) lv2 = 1; + double lv3 = v3.Length2 (); + if (!lv3) 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); +} + +Point<3> Ellipsoid :: GetSurfacePoint () const +{ + return a + v1; +} + + + +void Ellipsoid :: GetTriangleApproximation +(TriangleApproximation & tas, + const Box<3> & boundingbox, double facets) const +{ + int i, j; + double lg, bg; + int n = int(facets) + 1; + + for (j = 0; j <= n; j++) + for (i = 0; i <= n; i++) + { + lg = 2 * M_PI * double (i) / n; + 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 (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)); + } +} + + + + + + + + + + + + + + + + + + + + +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 (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); + + /* + ez = p1 - a; + ez -= (ez * vab) * vap; + ez /= ez.Length(); + + ezt = Cross (vab, ez); + */ + +} + + +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 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) + + ((r * cos(lg)) * n1) + + ((r * 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)); + } +} + + + + + + + + + +EllipticCylinder :: +EllipticCylinder (const Point<3> & aa, + const Vec<3> & avl, const Vec<3> & avs) +{ + a = aa; + vl = avl; + vs = avs; + + CalcData(); + Print (cout); +} + + +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) lvl = 1; + double lvs = vs.Length2 (); + if (!lvs) 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 = va * hvl + va * hvs - 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/vs.Length2 (); +} + +Point<3> EllipticCylinder :: GetSurfacePoint () const +{ + return a + vl; +} + + + +void EllipticCylinder :: GetTriangleApproximation +(TriangleApproximation & tas, + const Box<3> & boundingbox, double facets) const +{ + int i, j; + double lg, bg; + int n = int(facets) + 1; + + Vec<3> axis = Cross (vl, vs); + + for (j = 0; j <= n; j++) + for (i = 0; i <= n; i++) + { + lg = 2 * M_PI * double (i) / n; + bg = double(j) / n; + + Point<3> p = a + (bg * axis) + + cos(lg) * vl + sin(lg) * vs; + + 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)); + } +} + + + + + + + + + + +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 (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^2 + + + 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; + + (*testout) << "t0vec = " << t0vec << " t0 = " << t0 << endl; + (*testout) << "t1vec = " << t1vec << " t1 = " << t1 << endl; + PrintCoeff (*testout); +} + + +INSOLID_TYPE Cone :: BoxInSolid (const BoxSphere<3> & box) const +{ + double rp, dist; + + Vec<3> cv(box.Center()); + + rp = cv * t1vec + t1; + dist = sqrt (CalcFunctionValue(box.Center()) + rp * rp) - rp; + + if (dist - box.Diam() > 0) return IS_OUTSIDE; + if (dist + box.Diam() < 0) return IS_INSIDE; + return DOES_INTERSECT; +} + + +double Cone :: HesseNorm () const +{ + return 2 / minr; // old: 2 / minr +} + +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)); + } +} +} diff --git a/Netgen/libsrc/csg/algprim.hpp b/Netgen/libsrc/csg/algprim.hpp new file mode 100644 index 0000000000..83261edd16 --- /dev/null +++ b/Netgen/libsrc/csg/algprim.hpp @@ -0,0 +1,331 @@ +#ifndef FILE_ALGPRIM +#define FILE_ALGPRIM + + +/**************************************************************************/ +/* File: algprim.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 1. Dez. 95 */ +/**************************************************************************/ + +/* + +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; +public: + /// + Plane (const Point<3> & ap, Vec<3> an); + + virtual void GetPrimitiveData (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; + + /// + 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 GetTriangleApproximation + (TriangleApproximation & tas, + const Box<3> & boundingbox, double facets) const; + +}; + +// typedef Plane Plane; + + +/// +class Sphere : public QuadraticSurface +{ + /// + Point<3> c; + /// + double r; +public: + /// + Sphere (const Point<3> & ac, double ar); + + virtual void GetPrimitiveData (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> & 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); + + virtual void GetPrimitiveData (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); + + /* + static Primitive * CreateDefault (); + virtual void GetPrimitiveData (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; + +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 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; +public: + /// + Cone (const Point<3> & aa, const Point<3> & ab, double ara, double arb); + /// + static Primitive * CreateDefault (); + virtual void GetPrimitiveData (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; + +private: + void CalcData(); +}; + + +#endif diff --git a/Netgen/libsrc/csg/brick.cpp b/Netgen/libsrc/csg/brick.cpp new file mode 100644 index 0000000000..e4224ae512 --- /dev/null +++ b/Netgen/libsrc/csg/brick.cpp @@ -0,0 +1,409 @@ +#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; + s2.GetNormalVector(p1, n2); + 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)); +} + + +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; + + 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]->CalcFunctionValue (p); + + 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] -> CalcFunctionValue (p); + for (int i = 1; i < 6; i++) + { + double val = faces[i] -> 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 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); + */ +} + + +void Brick :: +GetPrimitiveData (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> p1 = pi[lface[i][0]-1]; + const Point<3> p2 = pi[lface[i][1]-1]; + const Point<3> p3 = pi[lface[i][2]-1]; + + Vec<3> n = Cross ((p2-p1), (p3-p1)); + n.Normalize(); + + for (j = 0; j < 3; j++) + { + data[j] = p1(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; + 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]->CalcFunctionValue (p); + if (val > 0) hasout = 1; + else if (val < 0) hasin = 1; + } + 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/Netgen/libsrc/csg/brick.hpp b/Netgen/libsrc/csg/brick.hpp new file mode 100644 index 0000000000..1733335101 --- /dev/null +++ b/Netgen/libsrc/csg/brick.hpp @@ -0,0 +1,97 @@ +#ifndef FILE_BRICK +#define FILE_BRICK + + +/**************************************************************************/ +/* File: brick.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 11. Mar. 98 */ +/**************************************************************************/ + +/* + + 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; + +public: + Brick (Point<3> ap1, Point<3> ap2, Point<3> ap3, Point<3> ap4); + ~Brick (); + 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; + + 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 (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/Netgen/libsrc/csg/bspline2d.cpp b/Netgen/libsrc/csg/bspline2d.cpp new file mode 100644 index 0000000000..ebb284a28b --- /dev/null +++ b/Netgen/libsrc/csg/bspline2d.cpp @@ -0,0 +1,243 @@ +#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; + char ch; + // cin >> ch; + return scal >= 0; +} + +double BSplineCurve2d :: ProjectParam (const Point<2> & p) const +{ + double t, dt, mindist, mint; + 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 loct, ddb1, ddb2, ddb3, ddb4; + Vec<2> hv; + + n = int(t); + // 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/Netgen/libsrc/csg/csg.hpp b/Netgen/libsrc/csg/csg.hpp new file mode 100644 index 0000000000..08dd054901 --- /dev/null +++ b/Netgen/libsrc/csg/csg.hpp @@ -0,0 +1,43 @@ +#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> + +namespace netgen +{ +#include "surface.hpp" +#include "solid.hpp" +#include "identify.hpp" +#include "singularref.hpp" + +#include "csgeom.hpp" +#include "triapprox.hpp" + + +#include "algprim.hpp" +#include "brick.hpp" +#include "spline3d.hpp" +// #include "spline2d.hpp" +#include "manifold.hpp" +#include "curve2d.hpp" +#include "explicitcurve2d.hpp" +#include "gencyl.hpp" +#include "polyhedra.hpp" +#include "extrusion.hpp" +#include "revolution.hpp" + +// #include "geom2dmesh.hpp" +#include "specpoin.hpp" +#include "edgeflw.hpp" +#include "meshsurf.hpp" +} + +#endif diff --git a/Netgen/libsrc/csg/csgeom.cpp b/Netgen/libsrc/csg/csgeom.cpp new file mode 100644 index 0000000000..7e1051b781 --- /dev/null +++ b/Netgen/libsrc/csg/csgeom.cpp @@ -0,0 +1,1067 @@ +#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); +} + +void TopLevelObject :: GetData (ostream & ost) +{ + ost << red << " " << green << " " << blue << " " + << transp << " " << visible << " "; +} + +void TopLevelObject :: SetData (istream & ist) +{ + ist >> red >> green >> blue >> transp >> visible; +} + + + + + +CSGeometry :: CSGeometry () + : boundingbox (Point<3> (-1000, -1000, -1000), + Point<3> (1000, 1000, 1000)), + identicsurfaces (100), filename("") +{ + ; +} + + + +CSGeometry :: CSGeometry (const string & afilename) + : boundingbox (Point<3> (-1000, -1000, -1000), + Point<3> (1000, 1000, 1000)), + identicsurfaces (100), filename(afilename) +{ + changeval++; +} + +CSGeometry :: ~CSGeometry () +{ + Clean(); +} + + +void CSGeometry :: Clean () +{ + int i; + + // for (i = 0; i < solids.Size(); i++) + // delete solids[i]; + solids.DeleteAll (); + + for (i = 0; i < surfaces.Size(); i++) + delete surfaces[i]; + surfaces.DeleteAll (); + + for (i = 0; i < toplevelobjects.Size(); i++) + delete toplevelobjects[i]; + toplevelobjects.DeleteAll (); + + for (i = 0; i < triapprox.Size(); i++) + delete triapprox[i]; + triapprox.DeleteAll(); + + changeval++; +} + + + + + +class WritePrimitivesIt : public SolidIterator +{ + ostream & ost; +public: + WritePrimitivesIt (ostream & aost); + ~WritePrimitivesIt (); + virtual void Do (Solid * sol); +}; + +WritePrimitivesIt :: WritePrimitivesIt (ostream & aost) + : SolidIterator(), ost(aost) +{ + ; +} +WritePrimitivesIt :: ~WritePrimitivesIt () +{ + ; +} + +void WritePrimitivesIt :: Do (Solid * sol) +{ + Primitive * prim = sol->GetPrimitive(); + if (prim) + { + 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 (ostream & ost) +{ + 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); + + int i; + for (i = 0; i < solids.Size(); i++) + { + if (!solids[i]->GetPrimitive()) + { + ost << "solid " << solids.GetName(i) << " "; + solids[i] -> GetSolidData (ost); + ost << endl; + } + } + + for (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 (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 :: 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) +{ + surfaces.Set (name, surf); + surf->SetName (name); + changeval++; +} + + +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 + return NULL; +} + + + + + +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; +} + + + + + + + + +class RemoveDummyIterator : public SolidIterator +{ +public: + + RemoveDummyIterator(); + ~RemoveDummyIterator(); + virtual void Do(Solid * sol); +}; + +RemoveDummyIterator :: RemoveDummyIterator() +{ + ; +} + +RemoveDummyIterator :: ~RemoveDummyIterator() +{ + ; +} + +void RemoveDummyIterator :: Do(Solid * sol) +{ + 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; +} + +void CSGeometry :: GetTopLevelObject (int nr, Solid *& sol, Surface *& surf) +{ + sol = toplevelobjects[nr]->GetSolid(); + surf = toplevelobjects[nr]->GetSurface(); +} + + +void CSGeometry :: GetTopLevelObject (int nr, const Solid *& sol, const Surface *& surf) const +{ + sol = toplevelobjects[nr]->GetSolid(); + surf = toplevelobjects[nr]->GetSurface(); +} + +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.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); + } + } +} + +void CSGeometry :: FindIdenticSurfaces (double eps) +{ + int i, j; + int inv; + int nsurf = GetNSurf(); + + isidenticto.SetSize(nsurf); + for (i = 0; i < nsurf; i++) + isidenticto[i] = i; + + for (i = 0; i < nsurf; i++) + for (j = i+1; j < nsurf; j++) + if (GetSurface(j) -> IsIdentic (*GetSurface(i), inv, eps)) + { + INDEX_2 i2(i, j); + identicsurfaces.Set (i2, inv); + isidenticto[j] = isidenticto[i]; + // (*testout) << "surfaces " << i2 << " are identic" << endl; + } + + /* + (*testout) << "identicmap:" << endl; + for (i = 0; i < isidenticto.Size(); i++) + (*testout) << i << " -> " << isidenticto[i] << endl; + + for (i = 0; i < nsurf; i++) + GetSurface(i)->Print (*testout); + */ +} + + +void CSGeometry :: +GetIndependentSurfaceIndices (const Solid * sol, + const BoxSphere<3> & box, + ARRAY<int> & locsurf) const +{ + int i, j; + + ReducePrimitiveIterator rpi(box); + UnReducePrimitiveIterator urpi; + + ((Solid*)sol) -> IterateSolid (rpi); + sol -> GetSurfaceIndices (locsurf); + ((Solid*)sol) -> IterateSolid (urpi); + + int cntindep = 0; + bool indep; + for (i = locsurf.Size()-1; i >= 0; i--) + { + indep = 1; + for (j = 0; j < i; j++) + { + INDEX_2 i2(locsurf[i], locsurf[j]); + i2.Sort(); + if (identicsurfaces.Used (i2)) + { + indep = 0; + break; + } + } + if (!indep) + locsurf.Delete(i); + } + + for (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 +{ + Point<3> p2 = p + 1e-2 * v; + BoxSphere<3> box (p2, p2); + box.Increase (1e-3); + box.CalcDiamCenter(); + GetIndependentSurfaceIndices (sol, box, locsurf); +} + + +void CSGeometry :: +CalcTriangleApproximation(const Box<3> & boundingbox, + double detail, double facets) +{ + PrintMessage (1, "Calc Triangle Approximation"); + + FindIdenticSurfaces (1e-6); + + int i, j, k; + // int nms = GetNMainSolids (); + int ntlo = GetNTopLevelObjects(); + + triapprox.SetSize (ntlo); + ARRAY<int> surfind; + + // cout << "bb = " << boundingbox.PMin () << " - " << boundingbox.PMax() << endl; + + for (i = 0; i < ntlo; i++) + { + Solid * sol; + Surface * surf; + GetTopLevelObject (i, sol, surf); + + // ((Solid*)MainSolid (i)) -> CalcSurfaceInverse (); + sol -> CalcSurfaceInverse (); + + TriangleApproximation * tams = new TriangleApproximation(); + triapprox[i] = tams; + + for (j = 0; j < GetNSurf(); j++) + { + PrintMessageCR (3, "Surface ", j, "/", GetNSurf()); + if (surf && surf != GetSurface(j)) + continue; + + TriangleApproximation tas; + GetSurface (j) -> GetTriangleApproximation (tas, boundingbox, facets); + + + int oldnp = tams -> GetNP(); + + if (!tas.GetNP()) + continue; + + for (k = 0; k < tas.GetNP(); k++) + { + Vec<3> n; + + tams -> AddPoint (tas.GetPoint(k)); + GetSurface(j) -> GetNormalVector (tas.GetPoint(k), n); + n.Normalize(); + if (GetSurface(j)->Inverse()) n *= -1; + tams -> AddNormal (n); + } + + + BoxSphere<3> surfbox; + + if (tas.GetNP()) + surfbox.Set (tas.GetPoint(0)); + for (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 (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); + delete locsol; + } + } + + } + + tams->RemoveUnusedPoints (); + PrintMessage (2, "Object ", i, " has ", tams->GetNT(), " triangles"); + } + + Change(); +} + + + +void CSGeometry :: +RefineTriangleApprox (Solid * locsol, + int surfind, + const BoxSphere<3> & box, + double detail, + const TATriangle & tria, + TriangleApproximation & tams) +{ + int i, j; + + // ARRAY<int> lsurfi; + int pinds[6]; + + static ARRAY<int> surfused; + surfused.SetSize(GetNSurf()); + + + ReducePrimitiveIterator rpi(box); + UnReducePrimitiveIterator urpi; + + + locsol -> IterateSolid (rpi); + // locsol -> GetSurfaceIndices (lsurfi); + + + IndexSet iset(GetNSurf()); + locsol -> GetSurfaceIndices (iset); + const ARRAY<int> & lsurfi = iset.Array(); + + locsol -> IterateSolid (urpi); + + + int surfii = -1; + for (i = 0; i < lsurfi.Size(); i++) + if (lsurfi[i] == surfind) + { + surfii = i; + break; + } + + if (surfii == -1) + return; + + + int cntindep = 0; + + for (i = 0; i < lsurfi.Size(); i++) + { + int linkto = isidenticto[lsurfi[i]]; + surfused[linkto] = 0; + } + + for (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) + { + // (*testout) << "add trig of surf " << surfind << endl; + if (cntindep > 1) (*testout) << "not unique" << endl; + tams.AddTriangle (tria); + return; + } + + if (cntindep == 2) + { + // just 2 surfaces: + // if smooth, project inner points to edge and finish + + int otherind; + + for (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 (); // Loc (box.Center(), box.Diam()); + + 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 (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); + } + + for (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 = Center (p1, p2); + + Point<3> pn; + if ( fabs (f1-f2) > 1e-20 ) + { + double l2 = -f1/(f2-f1); + double 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; + } + + pnums[lpin] = tams.AddPoint (pn); + + GetSurface (surfind)->Project (pn); + + Vec<3> n; + GetSurface (surfind)->GetNormalVector (pn, n); + 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 (j = 0; j < 3; j++) + if (onsurface[j]) + nvis++; + + for (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]); + 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) + return; + + for (i = 0; i < 3; i++) + pinds[i] = tria[i]; + + static int between[3][3] = + { { 0, 1, 5 }, + { 0, 2, 4 }, + { 1, 2, 3 } }; + + for (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); + GetSurface(surfind)->GetNormalVector (newp, n); + + 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 (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-6); + nbox.CalcDiamCenter(); + + Solid * nsol = locsol -> GetReducedSolid (nbox); + + if (nsol) + { + RefineTriangleApprox (nsol, surfind, nbox, + detail, ntri, tams); + + delete nsol; + } + } +} + + + + + +class ClearVisitedIt : public SolidIterator +{ +public: + ClearVisitedIt (); + ~ClearVisitedIt (); + virtual void Do (Solid * sol); +}; + +ClearVisitedIt :: ClearVisitedIt () +{ + ; +} +ClearVisitedIt :: ~ClearVisitedIt () +{ + ; +} + +void ClearVisitedIt :: Do (Solid * sol) +{ + sol -> visited = 0; +} + + + +void CSGeometry :: +IterateAllSolids (SolidIterator & it, int only_once) +{ + int i; + + if (only_once) + { + ClearVisitedIt clit; + for (i = 0; i < solids.Size(); i++) + solids[i] -> IterateSolid (clit, 0); + + } + + for (i = 0; i < solids.Size(); i++) + solids[i] -> IterateSolid (it, only_once); +} + + + +/* +const Box<3> & CSGeometry :: BoundingBox () const +{ + return boundingbox; +} +*/ + +void CSGeometry :: SetBoundingBox (const Box<3> & abox) +{ + boundingbox = abox; +} + +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/Netgen/libsrc/csg/csgeom.hpp b/Netgen/libsrc/csg/csgeom.hpp new file mode 100644 index 0000000000..4a8e32b28f --- /dev/null +++ b/Netgen/libsrc/csg/csgeom.hpp @@ -0,0 +1,241 @@ +#ifndef FILE_CSGEOM +#define FILE_CSGEOM + +/**************************************************************************/ +/* File: csgeom.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 27. Nov. 97 */ +/**************************************************************************/ + +/** + 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 +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; } +}; + + +/** + CSGeometry has the whole geometric information + */ +class CSGeometry +{ +private: + /// all surfaces + SYMBOLTABLE<Surface*> surfaces; + + /// all named solids + SYMBOLTABLE<Solid*> solids; + + /// all top level objects: solids and surfaces + ARRAY<TopLevelObject*> toplevelobjects; + + /// additional points specified by user + ARRAY<Point<3> > userpoints; + + /// triangular approximation of top level objects + ARRAY<TriangleApproximation*> triapprox; + + /// increment, if geometry is changed + static int changeval; + + /// bounding box of geometry + Box<3> 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, ...) + + + + /// filename of inputfile + string filename; + +public: + CSGeometry (); + CSGeometry (const string & afilename); + ~CSGeometry (); + + void Clean (); + + void Save (ostream & ost); + void Load (istream & ist); + + int GetChangeVal() { return changeval; } + void Change() { changeval++; } + + void AddSurface (Surface * surf); + void AddSurface (char * name, Surface * surf); + + int GetNSurf () const { return surfaces.Size(); } + const Surface * GetSurface (const char * name) const; + const Surface * GetSurface (int i) const; + + 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) { return solids[i]; } + const SYMBOLTABLE<Solid*> & GetSolids () const { return solids; } + + + void SetFlags (const char * solidname, const Flags & flags); + + /* + /// + void FindMainSolids (); + /// + int GetNMainSolids () const + { return mainsolids.Size(); } + /// + const Solid* MainSolid(int i) const + { return mainsolids.Get(i); } + */ + + + int GetNTopLevelObjects () const { return toplevelobjects.Size(); } + int SetTopLevelObject (Solid * sol, Surface * surf = NULL); + void GetTopLevelObject (int nr, Solid *& sol, Surface *& surf); + void GetTopLevelObject (int nr, const Solid *& sol, const Surface *& surf) const; + TopLevelObject * GetTopLevelObject (const Solid * sol, const Surface * surf = NULL); + TopLevelObject * GetTopLevelObject (int nr) + { 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) + { userpoints.Append (p); } + int GetNUserPoints () const + { return userpoints.Size(); } + const Point<3> & GetUserPoint (int nr) const + { return userpoints[nr]; } + + + // quick implementations: + ARRAY<SingularEdge*> singedges; + ARRAY<SingularPoint*> singpoints; + ARRAY<Identification*> identifications; + + int GetNIdentifications () { return identifications.Size(); } + void AddIdentification (Identification * ident); + + + /// + void CalcTriangleApproximation(const Box<3> & boundingbox, + double detail, double facets); + + /// + void FindIdenticSurfaces (double eps); + /// + 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; + /// + 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, int only_once = 0); + + void RefineTriangleApprox (Solid * locsol, + int surfind, + const BoxSphere<3> & box, + double detail, + const TATriangle & tria, + TriangleApproximation & tams); + + const Box<3> & BoundingBox () const { return boundingbox; } + void SetBoundingBox (const Box<3> & abox); + + double MaxSize () const; + + + + class BCModification { + public: + int si; + int tlonr; + int bcnr; + }; + ARRAY<BCModification> bcmodifications; + +}; +#endif + diff --git a/Netgen/libsrc/csg/csgparser.cpp b/Netgen/libsrc/csg/csgparser.cpp new file mode 100644 index 0000000000..9372d5675d --- /dev/null +++ b/Netgen/libsrc/csg/csgparser.cpp @@ -0,0 +1,1186 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> + + +namespace netgen +{ + using 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_IDENTIFY, TOK_CLOSESURFACES, + TOK_CLOSEEDGES, TOK_PERIODIC, + TOK_SOLID, TOK_RECO, TOK_TLO, TOK_BOUNDINGBOX, TOK_BOUNDARYCONDITION, + TOK_END }; + + struct kwstruct + { + TOKEN_TYPE kw; + char * name; + }; + + static kwstruct defkw[] = + { + { TOK_RECO, "algebraic3d" }, + { TOK_SOLID, "solid" }, + { TOK_TLO, "tlo" }, + { TOK_BOUNDINGBOX, "boundingbox" }, + { TOK_OR, "or" }, + { TOK_AND, "and" }, + { TOK_NOT, "not" }, + { TOK_SINGULAR, "singular" }, + { TOK_EDGE, "edge" }, + { TOK_POINT, "point" }, + { TOK_IDENTIFY, "identify" }, + { TOK_CLOSESURFACES, "closesurfaces" }, + { TOK_CLOSEEDGES, "closeedges" }, + { TOK_PERIODIC, "periodic" }, + { TOK_BOUNDARYCONDITION, "boundarycondition" }, + { TOKEN_TYPE(0) } + }; + + enum PRIMITIVE_TYPE + { TOK_SPHERE = 1, TOK_CYLINDER, TOK_PLANE, TOK_ELLIPTICCYLINDER, + TOK_ELLIPSOID, + TOK_CONE, TOK_TUBE, + TOK_GENCYL, TOK_ORTHOBRICK, TOK_POLYHEDRON, TOK_EXTRUSION, TOK_REVOLUTION, + TOK_TRANSLATE, TOK_MULTITRANSLATE, TOK_ROTATE, TOK_MULTIROTATE + }; + + struct primstruct + { + PRIMITIVE_TYPE kw; + char * name; + }; + + static primstruct defprim[] = + { + { TOK_PLANE, "plane" }, + { TOK_SPHERE, "sphere" }, + { TOK_CYLINDER, "cylinder" }, + { TOK_CONE, "cone" }, + { TOK_ELLIPTICCYLINDER, "ellipticcylinder" }, + { TOK_ELLIPSOID, "ellipsoid" }, + { TOK_TUBE, "tube" }, + { TOK_GENCYL, "gencyl" }, + { TOK_ORTHOBRICK, "orthobrick" }, + { TOK_POLYHEDRON, "polyhedron" }, + { TOK_EXTRUSION, "extrusion" }, + { TOK_REVOLUTION, "revolution" }, + + { TOK_TRANSLATE, "translate" }, + { TOK_MULTITRANSLATE, "multitranslate" }, + { TOK_ROTATE, "rotate" }, + { TOK_MULTIROTATE, "multirotate" }, + { PRIMITIVE_TYPE(0) } + }; + + + + static CSGeometry * geom; + + /* +%token <solidtype> TOK_SPHERE TOK_CYLINDER TOK_CONE TOK_PLAIN TOK_TUBE TOK_GENCYL TOK_ORTHOBRICK TOK_POLYHEDRON TOK_REVOLUTION +%left <solidtype> TOK_OR TOK_AND TOK_NOT +%token <solidtype> TOK_TRANSLATE TOK_MULTITRANSLATE TOK_ROTATE TOK_MULTIROTATE +%type <solidtype> solid solidprimitive +%type <void> splinesegmentlist splinesegment readbspline bsplinepointlist +%type <chptr> anyident +%token TOK_SINGULAR TOK_EDGE TOK_POINT +%token TOK_IDENTIFY TOK_CLOSESURFACES TOK_CLOSEEDGES TOK_PERIODIC +%token TOK_BOUNDARYCONDITION +%type <void> polyhedronpoints polyhedronfaces polyhedronpoint polyhedronface +%type <void> revolutionpoints revolutionpoint + */ + + + + 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(); + void Error (const string & err); + }; + + + CSGScanner :: CSGScanner (istream & ascanin) + { + scanin = &ascanin; + token = TOK_END; + num_value = 0; + linenum = 1; + } + + + void CSGScanner :: ReadNext () + { + char ch; + + + // whitespaces ueberspringen + do + { + scanin->get(ch); + + if (ch == '\n') + linenum++; + + // end of file reached + if (scanin->eof()) + { + token = TOK_END; + return; + } + + // 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)) + { + string_value += ch; + scanin->get(ch); + } + scanin->putback (ch); + } + /* + (*scanin).putback (ch); + (*scanin) >> string_value; + */ + 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) + { + char str[2]; + str[0] = ch; + str[1] = 0; + if (scan.GetToken() != TOKEN_TYPE(ch)) + scan.Error (string ("token '") + string(str) + 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; + } + + + Solid * ParseSolid (CSGScanner & scan); + Solid * ParseTerm (CSGScanner & scan); + Solid * ParsePrimary (CSGScanner & scan); + + + Solid * ParsePrimary (CSGScanner & scan) + { + if (scan.GetToken() == TOK_PRIMITIVE) + { + // cout << "prim token = " << int (scan.GetPrimitiveToken()) << endl; + switch (scan.GetPrimitiveToken()) + { + case TOK_PLANE: + { + Point<3> p; + Vec<3> v; + + scan.ReadNext(); + + ParseChar (scan, '('); + p(0) = ParseNumber (scan); + ParseChar (scan, ','); + p(1) = ParseNumber (scan); + ParseChar (scan, ','); + p(2) = ParseNumber (scan); + ParseChar (scan, ';'); + v(0) = ParseNumber (scan); + ParseChar (scan, ','); + v(1) = ParseNumber (scan); + ParseChar (scan, ','); + v(2) = ParseNumber (scan); + ParseChar (scan, ')'); + + // cout << "define plane, p = " << p << "; v = " << v << endl; + OneSurfacePrimitive * surf = new Plane ( p, v ); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + } + case TOK_CYLINDER: + { + Point<3> pa, pb; + double r; + + scan.ReadNext(); + + ParseChar (scan, '('); + pa(0) = ParseNumber (scan); + ParseChar (scan, ','); + pa(1) = ParseNumber (scan); + ParseChar (scan, ','); + pa(2) = ParseNumber (scan); + ParseChar (scan, ';'); + pb(0) = ParseNumber (scan); + ParseChar (scan, ','); + pb(1) = ParseNumber (scan); + ParseChar (scan, ','); + pb(2) = ParseNumber (scan); + ParseChar (scan, ';'); + r = ParseNumber (scan); + ParseChar (scan, ')'); + + OneSurfacePrimitive * surf = new Cylinder ( pa, pb, r ); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + } + + case TOK_ELLIPTICCYLINDER: + { + Point<3> pa; + Vec<3> vl, vs; + + scan.ReadNext(); + + ParseChar (scan, '('); + pa(0) = ParseNumber (scan); + ParseChar (scan, ','); + pa(1) = ParseNumber (scan); + ParseChar (scan, ','); + pa(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + vl(0) = ParseNumber (scan); + ParseChar (scan, ','); + vl(1) = ParseNumber (scan); + ParseChar (scan, ','); + vl(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + vs(0) = ParseNumber (scan); + ParseChar (scan, ','); + vs(1) = ParseNumber (scan); + ParseChar (scan, ','); + vs(2) = ParseNumber (scan); + ParseChar (scan, ')'); + + OneSurfacePrimitive * surf = new EllipticCylinder ( pa, vl, vs); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + } + + + case TOK_ELLIPSOID: + { + Point<3> pa; + Vec<3> v1, v2, v3; + + scan.ReadNext(); + + ParseChar (scan, '('); + pa(0) = ParseNumber (scan); + ParseChar (scan, ','); + pa(1) = ParseNumber (scan); + ParseChar (scan, ','); + pa(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + v1(0) = ParseNumber (scan); + ParseChar (scan, ','); + v1(1) = ParseNumber (scan); + ParseChar (scan, ','); + v1(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + v2(0) = ParseNumber (scan); + ParseChar (scan, ','); + v2(1) = ParseNumber (scan); + ParseChar (scan, ','); + v2(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + v3(0) = ParseNumber (scan); + ParseChar (scan, ','); + v3(1) = ParseNumber (scan); + ParseChar (scan, ','); + v3(2) = ParseNumber (scan); + ParseChar (scan, ')'); + + OneSurfacePrimitive * surf = new Ellipsoid ( pa, v1, v2, v3); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + } + + + case TOK_CONE: + { + Point<3> pa, pb; + double ra, rb; + + scan.ReadNext(); + + ParseChar (scan, '('); + pa(0) = ParseNumber (scan); + ParseChar (scan, ','); + pa(1) = ParseNumber (scan); + ParseChar (scan, ','); + pa(2) = ParseNumber (scan); + ParseChar (scan, ';'); + ra = ParseNumber (scan); + ParseChar (scan, ';'); + pb(0) = ParseNumber (scan); + ParseChar (scan, ','); + pb(1) = ParseNumber (scan); + ParseChar (scan, ','); + pb(2) = ParseNumber (scan); + ParseChar (scan, ';'); + rb = ParseNumber (scan); + ParseChar (scan, ')'); + + OneSurfacePrimitive * surf = new Cone ( pa, pb, ra, rb); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + } + + + + + case TOK_SPHERE: + { + Point<3> p; + double r; + + scan.ReadNext(); + + ParseChar (scan, '('); + p(0) = ParseNumber (scan); + ParseChar (scan, ','); + p(1) = ParseNumber (scan); + ParseChar (scan, ','); + p(2) = ParseNumber (scan); + ParseChar (scan, ';'); + r = ParseNumber (scan); + ParseChar (scan, ')'); + + // cout << "define sphere, c = " << p << ", rad = " << r << endl; + OneSurfacePrimitive * surf = new Sphere ( p, r ); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + } + + case TOK_ORTHOBRICK: + { + Point<3> pa, pb; + + scan.ReadNext(); + + ParseChar (scan, '('); + pa(0) = ParseNumber (scan); + ParseChar (scan, ','); + pa(1) = ParseNumber (scan); + ParseChar (scan, ','); + pa(2) = ParseNumber (scan); + ParseChar (scan, ';'); + pb(0) = ParseNumber (scan); + ParseChar (scan, ','); + pb(1) = ParseNumber (scan); + ParseChar (scan, ','); + pb(2) = ParseNumber (scan); + ParseChar (scan, ')'); + + // cout << "define orthobrick, p1 = " << pa << "; p2 = " << pb << endl; + + Primitive * nprim = new OrthoBrick (pa, pb); + + for (int j = 0; j < nprim->GetNSurfaces(); j++) + { + geom->AddSurface (&nprim->GetSurface(j)); + nprim->SetSurfaceId (j, geom->GetNSurf()-1); + } + 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(0) = ParseNumber (scan); + ParseChar (scan, ','); + p(1) = ParseNumber (scan); + ParseChar (scan, ','); + p(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + // cout << "point = " << p << endl; + + polyhedron->AddPoint(p); + + if (scan.GetToken() == ';') + { + scan.ReadNext(); + break; + } + } + + // scanning the faces + while (1) + { + pi1 = (int) (ParseNumber (scan)); + ParseChar (scan, ','); + pi2 = (int) (ParseNumber (scan)); + ParseChar (scan, ','); + pi3 = (int) (ParseNumber (scan)); + + polyhedron->AddFace(pi1-1,pi2-1,pi3-1); + + if (scan.GetToken() == TOK_COMMA) + { + ParseChar (scan, ','); + pi4 = (int) (ParseNumber (scan)); + polyhedron->AddFace(pi1-1,pi3-1,pi4-1); + } + + if (scan.GetToken() == ')') + { + scan.ReadNext(); + break; + } + scan.ReadNext(); + } + + for (int j = 0; j < polyhedron->GetNSurfaces(); j++) + { + geom->AddSurface (&polyhedron->GetSurface(j)); + polyhedron->SetSurfaceId (j, geom->GetNSurf()-1); + } + + return new Solid (polyhedron); + } + + + case TOK_EXTRUSION: + { + Point<3> p0; + Vec<3> ex, ey; + ARRAY<Point<2> > points; + + scan.ReadNext(); + + ParseChar (scan, '('); + p0(0) = ParseNumber (scan); + ParseChar (scan, ','); + p0(1) = ParseNumber (scan); + ParseChar (scan, ','); + p0(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + ex(0) = ParseNumber (scan); + ParseChar (scan, ','); + ex(1) = ParseNumber (scan); + ParseChar (scan, ','); + ex(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + ey(0) = ParseNumber (scan); + ParseChar (scan, ','); + ey(1) = ParseNumber (scan); + ParseChar (scan, ','); + ey(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + cout << "p0 = " << p0 << endl; + + int npseg = 0; + int nseg = 0; + while (1) + { + Point<2> p1, p2, p3; + + p1(0) = ParseNumber(scan); + ParseChar (scan, ','); + p1(1) = ParseNumber(scan); + points.Append (p1); + if (scan.GetToken() == ')') + { + scan.ReadNext(); + break; + } + scan.ReadNext(); + } + + + /* + while (1) + { + Point<2> p1, p2, p3; + + p3 = p2; + p2 = p1; + p1(0) = ParseNumber(scan); + ParseChar (scan, ','); + p1(1) = ParseNumber(scan); + npseg++; + + cout << "p1 = " << p1 << endl; + + if (scan.GetToken() == ';' || scan.GetToken() == ')') + { + if (npseg == 2) + { + p3 = p2; + p2 = Center (p1, p3); + } + if (nseg == 0) + points.Append (p3); + points.Append (p2); + points.Append (p1); + npseg = 1; + nseg++; + + cout << "p1, = " << p1 << ", p2 = " << p2 << ", p3 = " << p3 << endl; + } + + if (scan.GetToken() == ')') + { + scan.ReadNext(); + break; + } + if (scan.GetToken() == ';' || scan.GetToken() == ',') + { + scan.ReadNext(); + } + } + */ + cout << "p0 = " << p0 << endl; + cout << ", ex = " << ex << ", ey = " << ey << endl; + cout << "points = " << points << endl; + + Extrusion * extrusion = new Extrusion (p0, ex, ey, points); + + for (int i = 0; i < extrusion->GetNSurfaces(); i++) + { + geom->AddSurface (&extrusion->GetSurface(i)); + extrusion->SetSurfaceId(i, geom->GetNSurf()-1); + } + return new Solid (extrusion); + + /* + // cout << "define cylinder, pa = " << pa << "; pb = " << pb + // << ", rad = " << r << endl; + OneSurfacePrimitive * surf = new Cylinder ( pa, pb, r ); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + */ + } + + + + + + case TOK_TRANSLATE: + { + Vec<3> v; + scan.ReadNext(); + ParseChar (scan, '('); + v(0) = ParseNumber (scan); + ParseChar (scan, ','); + v(1) = ParseNumber (scan); + ParseChar (scan, ','); + v(2) = ParseNumber (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_MULTITRANSLATE: + { + Vec<3> v; + int n; + + scan.ReadNext(); + ParseChar (scan, '('); + v(0) = ParseNumber (scan); + ParseChar (scan, ','); + v(1) = ParseNumber (scan); + ParseChar (scan, ','); + v(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + n = int (ParseNumber (scan)); + ParseChar (scan, ';'); + + Solid * sol1 = ParseSolid (scan); + + ParseChar (scan, ')'); + + int i; + Solid * hsol = sol1; + for (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; + } + + + 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; + } + + + + 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(); + 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 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, ';'); + + 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))); + } + } + + 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); + + geom->AddIdentification + (new CloseSurfaceIdentification + (geom->GetNIdentifications()+1, *geom, + geom->GetSurface (si1[0]), geom->GetSurface (si2[0]), + 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_POINT) + { + Point<3> p; + + scan.ReadNext(); + ParseChar (scan, '('); + p(0) = ParseNumber (scan); + ParseChar (scan, ','); + p(1) = ParseNumber (scan); + ParseChar (scan, ','); + p(2) = ParseNumber (scan); + ParseChar (scan, ')'); + ParseChar (scan, ';'); + + geom->AddUserPoint (p); + } + + else if (scan.GetToken() == TOK_BOUNDINGBOX) + { + Point<3> p1, p2; + + scan.ReadNext(); + ParseChar (scan, '('); + p1(0) = ParseNumber (scan); + ParseChar (scan, ','); + p1(1) = ParseNumber (scan); + ParseChar (scan, ','); + p1(2) = ParseNumber (scan); + ParseChar (scan, ';'); + p2(0) = ParseNumber (scan); + ParseChar (scan, ','); + p2(1) = ParseNumber (scan); + ParseChar (scan, ','); + p2(2) = ParseNumber (scan); + ParseChar (scan, ')'); + ParseChar (scan, ';'); + + geom->SetBoundingBox (Box<3> (p1, p2)); + } + + 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; + ARRAY<int> si; + + geom->GetSolid(name1)->GetSurfaceIndices(si); + + bcm.tlonr = -1; + int i; + for (i = 0; i < geom->GetNTopLevelObjects(); i++) + if (string (geom->GetTopLevelObject(i)->GetSolid()->Name()) + == name2) + { + bcm.tlonr = i; + break; + } + + bcm.bcnr = num; + for (i = 0; i < si.Size(); i++) + { + bcm.si = si[i]; + geom->bcmodifications.Append (bcm); + } + } + + else + { + cout << "read unidentified token " << scan.GetToken() + << " string = " << scan.GetStringValue() << endl; + scan.ReadNext(); + } + } + } + catch (string errstr) + { + cout << "caught error " << errstr << 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/Netgen/libsrc/csg/csgparser_dalibor.cpp b/Netgen/libsrc/csg/csgparser_dalibor.cpp new file mode 100644 index 0000000000..7f640864a3 --- /dev/null +++ b/Netgen/libsrc/csg/csgparser_dalibor.cpp @@ -0,0 +1,1111 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> + + +namespace netgen +{ + using 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_TRANSLATE, TOK_MULTITRANSLATE, TOK_ROTATE, TOK_MULTIROTATE, + TOK_SINGULAR, TOK_EDGE, TOK_POINT, TOK_IDENTIFY, TOK_CLOSESURFACES, + TOK_CLOSEEDGES, TOK_PERIODIC, + TOK_SOLID, TOK_RECO, TOK_TLO, TOK_BOUNDINGBOX, TOK_BOUNDARYCONDITION, + TOK_END }; + + struct kwstruct + { + TOKEN_TYPE kw; + char * name; + }; + + static kwstruct defkw[] = + { + { TOK_RECO, "algebraic3d" }, + { TOK_SOLID, "solid" }, + { TOK_TLO, "tlo" }, + { TOK_BOUNDINGBOX, "boundingbox" }, + { TOK_OR, "or" }, + { TOK_AND, "and" }, + { TOK_NOT, "not" }, + { TOK_TRANSLATE, "translate" }, + { TOK_MULTITRANSLATE, "multitranslate" }, + { TOK_ROTATE, "rotate" }, + { TOK_MULTIROTATE, "multirotate" }, + { TOK_SINGULAR, "singular" }, + { TOK_EDGE, "edge" }, + { TOK_POINT, "point" }, + { TOK_IDENTIFY, "identify" }, + { TOK_CLOSESURFACES, "closesurfaces" }, + { TOK_CLOSEEDGES, "closeedges" }, + { TOK_PERIODIC, "periodic" }, + { TOK_BOUNDARYCONDITION, "boundarycondition" }, + { TOKEN_TYPE(0) } + }; + + enum PRIMITIVE_TYPE + { TOK_SPHERE = 1, TOK_CYLINDER, TOK_PLANE, TOK_ELLIPTICCYLINDER, + TOK_ELLIPSOID, + TOK_CONE, TOK_TUBE, + TOK_GENCYL, TOK_ORTHOBRICK, TOK_POLYHEDRON, TOK_EXTRUSION, TOK_REVOLUTION }; + + struct primstruct + { + PRIMITIVE_TYPE kw; + char * name; + }; + + static primstruct defprim[] = + { + { TOK_PLANE, "plane" }, + { TOK_SPHERE, "sphere" }, + { TOK_CYLINDER, "cylinder" }, + { TOK_CONE, "cone" }, + { TOK_ELLIPTICCYLINDER, "ellipticcylinder" }, + { TOK_ELLIPSOID, "ellipsoid" }, + { TOK_TUBE, "tube" }, + { TOK_GENCYL, "gencyl" }, + { TOK_ORTHOBRICK, "orthobrick" }, + { TOK_POLYHEDRON, "polyhedron" }, + { TOK_EXTRUSION, "extrusion" }, + { TOK_REVOLUTION, "revolution" }, + { PRIMITIVE_TYPE(0) } + }; + + + + static CSGeometry * geom; + + /* +%token <solidtype> TOK_SPHERE TOK_CYLINDER TOK_CONE TOK_PLAIN TOK_TUBE TOK_GENCYL TOK_ORTHOBRICK TOK_POLYHEDRON TOK_REVOLUTION +%left <solidtype> TOK_OR TOK_AND TOK_NOT +%token <solidtype> TOK_TRANSLATE TOK_MULTITRANSLATE TOK_ROTATE TOK_MULTIROTATE +%type <solidtype> solid solidprimitive +%type <void> splinesegmentlist splinesegment readbspline bsplinepointlist +%type <chptr> anyident +%token TOK_SINGULAR TOK_EDGE TOK_POINT +%token TOK_IDENTIFY TOK_CLOSESURFACES TOK_CLOSEEDGES TOK_PERIODIC +%token TOK_BOUNDARYCONDITION +%type <void> polyhedronpoints polyhedronfaces polyhedronpoint polyhedronface +%type <void> revolutionpoints revolutionpoint + */ + + + + 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; } + + PRIMITIVE_TYPE GetPrimitiveToken() const + { return prim_token; } + + void ReadNext(); + void Error (const string & err); + }; + + + CSGScanner :: CSGScanner (istream & ascanin) + { + int i; + + scanin = &ascanin; + token = TOK_END; + num_value = 0; + linenum = 1; + } + + + void CSGScanner :: ReadNext () + { + char ch; + + + // whitespaces ueberspringen + do + { + scanin->get(ch); + + if (ch == '\n') + linenum++; + + // end of file reached + if (scanin->eof()) + { + token = TOK_END; + return; + } + + // 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)) + { + string_value += ch; + scanin->get(ch); + } + scanin->putback (ch); + } + /* + (*scanin).putback (ch); + (*scanin) >> string_value; + */ + 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) + { + char str[2]; + str[0] = ch; + str[1] = 0; + if (scan.GetToken() != TOKEN_TYPE(ch)) + scan.Error (string ("token '") + string(str) + 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; + } + + + Solid * ParseSolid (CSGScanner & scan); + Solid * ParseTerm (CSGScanner & scan); + Solid * ParsePrimary (CSGScanner & scan); + + + Solid * ParsePrimary (CSGScanner & scan) + { + if (scan.GetToken() == TOK_PRIMITIVE) + { + // cout << "prim token = " << int (scan.GetPrimitiveToken()) << endl; + switch (scan.GetPrimitiveToken()) + { + case TOK_PLANE: + { + Point<3> p; + Vec<3> v; + + scan.ReadNext(); + + ParseChar (scan, '('); + p(0) = ParseNumber (scan); + ParseChar (scan, ','); + p(1) = ParseNumber (scan); + ParseChar (scan, ','); + p(2) = ParseNumber (scan); + ParseChar (scan, ';'); + v(0) = ParseNumber (scan); + ParseChar (scan, ','); + v(1) = ParseNumber (scan); + ParseChar (scan, ','); + v(2) = ParseNumber (scan); + ParseChar (scan, ')'); + + // cout << "define plane, p = " << p << "; v = " << v << endl; + OneSurfacePrimitive * surf = new Plane ( p, v ); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + } + case TOK_CYLINDER: + { + Point<3> pa, pb; + double r; + + scan.ReadNext(); + + ParseChar (scan, '('); + pa(0) = ParseNumber (scan); + ParseChar (scan, ','); + pa(1) = ParseNumber (scan); + ParseChar (scan, ','); + pa(2) = ParseNumber (scan); + ParseChar (scan, ';'); + pb(0) = ParseNumber (scan); + ParseChar (scan, ','); + pb(1) = ParseNumber (scan); + ParseChar (scan, ','); + pb(2) = ParseNumber (scan); + ParseChar (scan, ';'); + r = ParseNumber (scan); + ParseChar (scan, ')'); + + OneSurfacePrimitive * surf = new Cylinder ( pa, pb, r ); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + } + + case TOK_ELLIPTICCYLINDER: + { + Point<3> pa; + Vec<3> vl, vs; + + scan.ReadNext(); + + ParseChar (scan, '('); + pa(0) = ParseNumber (scan); + ParseChar (scan, ','); + pa(1) = ParseNumber (scan); + ParseChar (scan, ','); + pa(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + vl(0) = ParseNumber (scan); + ParseChar (scan, ','); + vl(1) = ParseNumber (scan); + ParseChar (scan, ','); + vl(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + vs(0) = ParseNumber (scan); + ParseChar (scan, ','); + vs(1) = ParseNumber (scan); + ParseChar (scan, ','); + vs(2) = ParseNumber (scan); + ParseChar (scan, ')'); + + OneSurfacePrimitive * surf = new EllipticCylinder ( pa, vl, vs); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + } + + + case TOK_ELLIPSOID: + { + Point<3> pa; + Vec<3> v1, v2, v3; + + scan.ReadNext(); + + ParseChar (scan, '('); + pa(0) = ParseNumber (scan); + ParseChar (scan, ','); + pa(1) = ParseNumber (scan); + ParseChar (scan, ','); + pa(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + v1(0) = ParseNumber (scan); + ParseChar (scan, ','); + v1(1) = ParseNumber (scan); + ParseChar (scan, ','); + v1(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + v2(0) = ParseNumber (scan); + ParseChar (scan, ','); + v2(1) = ParseNumber (scan); + ParseChar (scan, ','); + v2(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + v3(0) = ParseNumber (scan); + ParseChar (scan, ','); + v3(1) = ParseNumber (scan); + ParseChar (scan, ','); + v3(2) = ParseNumber (scan); + ParseChar (scan, ')'); + + OneSurfacePrimitive * surf = new Ellipsoid ( pa, v1, v2, v3); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + } + + + case TOK_CONE: + { + Point<3> pa, pb; + double ra, rb; + + scan.ReadNext(); + + ParseChar (scan, '('); + pa(0) = ParseNumber (scan); + ParseChar (scan, ','); + pa(1) = ParseNumber (scan); + ParseChar (scan, ','); + pa(2) = ParseNumber (scan); + ParseChar (scan, ';'); + ra = ParseNumber (scan); + ParseChar (scan, ';'); + pb(0) = ParseNumber (scan); + ParseChar (scan, ','); + pb(1) = ParseNumber (scan); + ParseChar (scan, ','); + pb(2) = ParseNumber (scan); + ParseChar (scan, ';'); + rb = ParseNumber (scan); + ParseChar (scan, ')'); + + OneSurfacePrimitive * surf = new Cone ( pa, pb, ra, rb); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + } + + + + + case TOK_SPHERE: + { + Point<3> p; + double r; + + scan.ReadNext(); + + ParseChar (scan, '('); + p(0) = ParseNumber (scan); + ParseChar (scan, ','); + p(1) = ParseNumber (scan); + ParseChar (scan, ','); + p(2) = ParseNumber (scan); + ParseChar (scan, ';'); + r = ParseNumber (scan); + ParseChar (scan, ')'); + + // cout << "define sphere, c = " << p << ", rad = " << r << endl; + OneSurfacePrimitive * surf = new Sphere ( p, r ); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + } + + case TOK_ORTHOBRICK: + { + Point<3> pa, pb; + + scan.ReadNext(); + + ParseChar (scan, '('); + pa(0) = ParseNumber (scan); + ParseChar (scan, ','); + pa(1) = ParseNumber (scan); + ParseChar (scan, ','); + pa(2) = ParseNumber (scan); + ParseChar (scan, ';'); + pb(0) = ParseNumber (scan); + ParseChar (scan, ','); + pb(1) = ParseNumber (scan); + ParseChar (scan, ','); + pb(2) = ParseNumber (scan); + ParseChar (scan, ')'); + + // cout << "define orthobrick, p1 = " << pa << "; p2 = " << pb << endl; + + Primitive * nprim = new OrthoBrick (pa, pb); + + for (int j = 0; j < nprim->GetNSurfaces(); j++) + { + geom->AddSurface (&nprim->GetSurface(j)); + nprim->SetSurfaceId (j, geom->GetNSurf()-1); + } + return new Solid (nprim); + } + + + case TOK_EXTRUSION: + { + Point<3> p0; + Vec<3> ex, ey; + ARRAY<Point<2> > points; + + scan.ReadNext(); + + ParseChar (scan, '('); + p0(0) = ParseNumber (scan); + ParseChar (scan, ','); + p0(1) = ParseNumber (scan); + ParseChar (scan, ','); + p0(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + ex(0) = ParseNumber (scan); + ParseChar (scan, ','); + ex(1) = ParseNumber (scan); + ParseChar (scan, ','); + ex(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + ey(0) = ParseNumber (scan); + ParseChar (scan, ','); + ey(1) = ParseNumber (scan); + ParseChar (scan, ','); + ey(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + cout << "p0 = " << p0 << endl; + + int npseg = 0; + int nseg = 0; + while (1) + { + Point<2> p1, p2, p3; + + p1(0) = ParseNumber(scan); + ParseChar (scan, ','); + p1(1) = ParseNumber(scan); + points.Append (p1); + if (scan.GetToken() == ')') + { + scan.ReadNext(); + break; + } + scan.ReadNext(); + } + + + /* + while (1) + { + Point<2> p1, p2, p3; + + p3 = p2; + p2 = p1; + p1(0) = ParseNumber(scan); + ParseChar (scan, ','); + p1(1) = ParseNumber(scan); + npseg++; + + cout << "p1 = " << p1 << endl; + + if (scan.GetToken() == ';' || scan.GetToken() == ')') + { + if (npseg == 2) + { + p3 = p2; + p2 = Center (p1, p3); + } + if (nseg == 0) + points.Append (p3); + points.Append (p2); + points.Append (p1); + npseg = 1; + nseg++; + + cout << "p1, = " << p1 << ", p2 = " << p2 << ", p3 = " << p3 << endl; + } + + if (scan.GetToken() == ')') + { + scan.ReadNext(); + break; + } + if (scan.GetToken() == ';' || scan.GetToken() == ',') + { + scan.ReadNext(); + } + } + */ + cout << "p0 = " << p0 << endl; + cout << ", ex = " << ex << ", ey = " << ey << endl; + cout << "points = " << points << endl; + + Extrusion * extrusion = new Extrusion (p0, ex, ey, points); + + for (int i = 0; i < extrusion->GetNSurfaces(); i++) + { + geom->AddSurface (&extrusion->GetSurface(i)); + extrusion->SetSurfaceId(i, geom->GetNSurf()-1); + } + return new Solid (extrusion); + + /* + // cout << "define cylinder, pa = " << pa << "; pb = " << pb + // << ", rad = " << r << endl; + OneSurfacePrimitive * surf = new Cylinder ( pa, pb, r ); + + geom->AddSurface (surf); + surf->SetSurfaceId (0, geom->GetNSurf()-1); + + return new Solid (surf); + */ + } + + +// Added by Dalibor Lukas, October 15, 2003 + case TOK_POLYHEDRON: + { + Point<3> p; + int pi1, pi2, pi3, pi4; + + scan.ReadNext(); + ParseChar (scan, '('); + + Polyhedra * polyhedron = new Polyhedra; + + // scanning the points + while (1) + { + p(0) = ParseNumber (scan); + ParseChar (scan, ','); + p(1) = ParseNumber (scan); + ParseChar (scan, ','); + p(2) = ParseNumber (scan); + ParseChar (scan, ';'); + + cout << "point = " << p << endl; + + polyhedron->AddPoint(p); + + if (scan.GetToken() == ';') + { + scan.ReadNext(); + break; + } + } + + // scanning the faces + while (1) + { + pi1 = (int) (ParseNumber (scan)); + ParseChar (scan, ','); + pi2 = (int) (ParseNumber (scan)); + ParseChar (scan, ','); + pi3 = (int) (ParseNumber (scan)); + ParseChar (scan, ','); + pi4 = (int) (ParseNumber (scan)); + + cout << "face = (" << pi1 << ", " << pi2 << ", " << pi3 + << ", " << pi4 << ")" << endl; + + polyhedron->AddFace(pi1-1,pi2-1,pi3-1); + polyhedron->AddFace(pi1-1,pi3-1,pi4-1); + + if (scan.GetToken() == ')') + { + scan.ReadNext(); + break; + } + scan.ReadNext(); + } + + int j; + for (j = 0; j < polyhedron->GetNSurfaces(); j++) + { + geom->AddSurface (&polyhedron->GetSurface(j)); + polyhedron->SetSurfaceId (j, geom->GetNSurf()-1); + } + + return new Solid (polyhedron); + } +// DL + + + } + cout << "unknown primary " << scan.GetStringValue() << endl; + } + + 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; + } + + + + 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(); + 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 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, ';'); + + 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))); + } + } + + 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); + + geom->AddIdentification + (new CloseSurfaceIdentification + (geom->GetNIdentifications()+1, *geom, + geom->GetSurface (si1[0]), geom->GetSurface (si2[0]), + 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; + } + } + + } + + else if (scan.GetToken() == TOK_POINT) + { + Point<3> p; + + scan.ReadNext(); + ParseChar (scan, '('); + p(0) = ParseNumber (scan); + ParseChar (scan, ','); + p(1) = ParseNumber (scan); + ParseChar (scan, ','); + p(2) = ParseNumber (scan); + ParseChar (scan, ')'); + ParseChar (scan, ';'); + + geom->AddUserPoint (p); + } + + else if (scan.GetToken() == TOK_BOUNDINGBOX) + { + Point<3> p1, p2; + + scan.ReadNext(); + ParseChar (scan, '('); + p1(0) = ParseNumber (scan); + ParseChar (scan, ','); + p1(1) = ParseNumber (scan); + ParseChar (scan, ','); + p1(2) = ParseNumber (scan); + ParseChar (scan, ';'); + p2(0) = ParseNumber (scan); + ParseChar (scan, ','); + p2(1) = ParseNumber (scan); + ParseChar (scan, ','); + p2(2) = ParseNumber (scan); + ParseChar (scan, ')'); + ParseChar (scan, ';'); + + geom->SetBoundingBox (Box<3> (p1, p2)); + } + + 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; + ARRAY<int> si; + + geom->GetSolid(name1)->GetSurfaceIndices(si); + + bcm.tlonr = -1; + int i; + for (i = 0; i < geom->GetNTopLevelObjects(); i++) + if (string (geom->GetTopLevelObject(i)->GetSolid()->Name()) + == name2) + { + bcm.tlonr = i; + break; + } + + bcm.bcnr = num; + for (i = 0; i < si.Size(); i++) + { + bcm.si = si[i]; + geom->bcmodifications.Append (bcm); + } + } + + else + { + cout << "read unidentified token " << scan.GetToken() + << " string = " << scan.GetStringValue() << endl; + scan.ReadNext(); + } + } + } + catch (string errstr) + { + cout << "caught error " << errstr << 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/Netgen/libsrc/csg/csgscanner.cpp b/Netgen/libsrc/csg/csgscanner.cpp new file mode 100644 index 0000000000..50e2213ea6 --- /dev/null +++ b/Netgen/libsrc/csg/csgscanner.cpp @@ -0,0 +1,205 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> + + +namespace netgen +{ + using namespace netgen; + + + enum TOKEN_TYPE + { + LP = '(', RP = ')', EQU = '=', COMMA = ',', SEMICOLON = ';', + TOK_NUM, TOK_STRING, TOK_NAMED_SOLID, TOK_PRIMITIVE, + TOK_OR, TOK_AND, TOK_NOT, + TOK_SOLID, TOK_RECO, TOK_TLO, TOK_BOUNDINGBOX, + TOK_END }; + + struct kwstruct + { + TOKEN_TYPE kw; + string name; + }; + + static kwstruct defkw[] = + { + { TOK_OR, "or" }, + { TOK_AND, "and" }, + { TOKEN_TYPE(0) } + }; + + enum PRIMITIVE_TYPE { TOK_SPHERE, TOK_CYLINDER, TOK_PLANE }; + + /* +%token <solidtype> TOK_SPHERE TOK_CYLINDER TOK_CONE TOK_PLAIN TOK_TUBE TOK_GENCYL TOK_ORTHOBRICK TOK_POLYHEDRON TOK_REVOLUTION +%left <solidtype> TOK_OR TOK_AND TOK_NOT +%token <solidtype> TOK_TRANSLATE TOK_MULTITRANSLATE TOK_ROTATE TOK_MULTIROTATE +%type <solidtype> solid solidprimitive +%type <void> splinesegmentlist splinesegment readbspline bsplinepointlist +%type <chptr> anyident +%token TOK_SINGULAR TOK_EDGE TOK_POINT +%token TOK_IDENTIFY TOK_CLOSESURFACES TOK_CLOSEEDGES TOK_PERIODIC +%token TOK_BOUNDARYCONDITION +%type <void> polyhedronpoints polyhedronfaces polyhedronpoint polyhedronface +%type <void> revolutionpoints revolutionpoint + */ + + + + class CSGScanner + { + TOKEN_TYPE 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; } + + void ReadNext(); + + void Error (const string & err); + }; + + + CSGScanner :: CSGScanner (istream & ascanin) + { + int i; + + scanin = &ascanin; + token = TOK_END; + num_value = 0; + linenum = 1; + } + + + void CSGScanner :: ReadNext () + { + char ch; + + + // whitespaces ueberspringen + do + { + scanin->get(ch); + + if (ch == '\n') + linenum++; + + // end of file reached + if (scanin->eof()) + { + token = TOK_END; + return; + } + + // 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 ';': + { + token = TOKEN_TYPE (ch); + break; + } + + default: + { + if (isdigit (ch) || ch == '.' || ch == '-') + { + scanin->putback (ch); + (*scanin) >> num_value; + token = TOK_NUM; + return; + } + + (*scanin).putback (ch); + (*scanin) >> string_value; + + int nr = 0; + while (defkw[nr].kw) + { + if (string_value == defkw[nr].name) + { + token = defkw[nr].kw; + return; + } + } + + token = TOK_STRING; + } + } + } + + void CSGScanner :: Error (const string & err) + { + stringstream errstr; + errstr << "Parsing error in line " << linenum << ": " << endl << err << endl; + /* + errstr << "input continues with <<<"; + for (int i = 0; i < 50; i++) + { + char ch; + scanin->get(ch); + errstr << ch; + if (scanin->eof()) + { + errstr << "(end of file)"; + break; + } + } + errstr << endl << ">>> stop parsing" << endl; + throw Exception (errstr.str()); + */ + } + + + + + + void ParseCSG (istream & istr) + { + CSGScanner scan(istr); + + do + { + scan.ReadNext(); + cout << "token = " << int(scan.GetToken()) << endl; + } + while (scan.GetToken() != TOK_END); + } + + +}; + diff --git a/Netgen/libsrc/csg/curve2d.cpp b/Netgen/libsrc/csg/curve2d.cpp new file mode 100644 index 0000000000..7091e87af9 --- /dev/null +++ b/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/Netgen/libsrc/csg/curve2d.hpp b/Netgen/libsrc/csg/curve2d.hpp new file mode 100644 index 0000000000..917bd53205 --- /dev/null +++ b/Netgen/libsrc/csg/curve2d.hpp @@ -0,0 +1,59 @@ +#ifndef FILE_CURVE2D +#define FILE_CURVE2D + +/**************************************************************************/ +/* File: curve2d.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 24. Jul. 96 */ +/**************************************************************************/ + +/* + + 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/Netgen/libsrc/csg/edgeflw.cpp b/Netgen/libsrc/csg/edgeflw.cpp new file mode 100644 index 0000000000..0e5418ad69 --- /dev/null +++ b/Netgen/libsrc/csg/edgeflw.cpp @@ -0,0 +1,1399 @@ +#include <mystdlib.h> +#include <meshing.hpp> +#include <csg.hpp> + +#undef DEVELOP + +namespace netgen +{ + + EdgeCalculation :: + EdgeCalculation (const CSGeometry & ageometry, + const ARRAY<SpecialPoint> & aspecpoints) + : geometry(ageometry), specpoints(aspecpoints) + { + ; + } + + + + void EdgeCalculation :: Calc(double h, Mesh & mesh) + { + (*testout) << "Find edges" << endl; + PrintMessage (1, "Find edges"); + PushStatus ("Find edges"); + + CalcEdges1 (h, mesh); + SplitEqualOneSegEdges (mesh); + FindClosedSurfaces (h, mesh); + PrintMessage (3, cntedge, " edges found"); + PopStatus (); + } + + + + + + void EdgeCalculation :: CalcEdges1 (double h, Mesh & mesh) + { + ARRAY<SpecialPoint> hsp(specpoints.Size()); + ARRAY<SpecialPoint> startpoints, endpoints; + + int i, j, k, l, hi, pos, ep, ne; + int layer; + + Vec<3> a1, a2, t, n, m; + Point<3> p, np, pnp, hp; + + Segment seg; + int pi1, s1, s2; + int lastpi, thispi; + + ARRAY<Point<3> > edgepoints; + ARRAY<double> curvelength; + int copyedge, copyfromedge, copyedgeidentification; + + ARRAY<int> locsurfind; + + double len, corr, lam; + double steplen, cursteplen, loch, hd; + + int checkedcopy = 0; + + double size = geometry.MaxSize(); // globflags.GetNumFlag ("maxsize", 500); + double epspointdist2 = size * 1e-6; // globflags.GetNumFlag ("epspointdist", size * 1e-6); + epspointdist2 = sqr (epspointdist2); + + + Solid * locsol; + + + // copy special points to work with + for (i = 0; i < specpoints.Size(); i++) + hsp[i] = specpoints[i]; + + + cntedge = 0; + + while (hsp.Size()) + { + SetThreadPercent(100 - 100 * double (hsp.Size()) / specpoints.Size()); + + edgepoints.SetSize (0); + curvelength.SetSize (0); + + + pi1 = 0; + copyedge = 0; + // identifyable point available ? + + // (*testout) << endl; + + for (i = 1; i <= geometry.identifications.Size() && !pi1; i++) + { + for (j = checkedcopy+1; j <= startpoints.Size() && !pi1; j++) + { + + if (geometry.identifications.Get(i)->IdentifyableCandidate (startpoints.Get(j))) + + { + int pi1cand = 0; + double mindist = 1e10; + + for (k = 1; k <= hsp.Size() && !pi1; k++) + { +#ifdef DEVELOP + (*testout) << "check kand = " << hsp.Get(k).p + << ", v = " << hsp.Get(k).v + << endl; +#endif + if (geometry.identifications.Get(i) + ->Identifyable(startpoints.Get(j), hsp.Get(k)) || + geometry.identifications.Get(i) + ->Identifyable(hsp.Get(k), startpoints.Get(j))) + { + +#ifdef DEVELOP + (*testout) << "identifiable, dist = " + << Dist (startpoints.Get(j).p, hsp.Get(k).p) << endl; +#endif + + if (Dist (startpoints.Get(j).p, hsp.Get(k).p) < mindist) + { + mindist = Dist (startpoints.Get(j).p, hsp.Get(k).p); + pi1cand = k; + } + /* + pi1 = k; + copyedge = 1; + copyfromedge = j; + copyedgeidentification = i; + + (*testout) << "copy edge startpoint from " + << startpoints.Get(j).p << " - " + << startpoints.Get(j).v + << " to " + << hsp.Get(k).p << " - " << hsp.Get(k).v << endl; + */ + } + } + + if (pi1cand) + { + pi1 = pi1cand; + copyedge = 1; + copyfromedge = j; + copyedgeidentification = i; +#ifdef DEVELOP + (*testout) << "copy edge startpoint from " + << startpoints.Get(j).p << " - " + << startpoints.Get(j).v + << " to " + << hsp.Get(pi1).p << " - " << hsp.Get(pi1).v << endl; +#endif + } + } + } + } + + + // cannot copy from other ege ? + if (!pi1) + checkedcopy = startpoints.Size(); + + // unconditional special point available ? + if (!pi1) + for (i = 1; i <= hsp.Size() && pi1 == 0; i++) + if (hsp.Get(i).unconditional == 1) + pi1 = i; + + + if (!pi1) + { + // only unconditional points available, choose first + pi1 = 1; + } + + layer = hsp.Get(pi1).GetLayer(); + + + if (!hsp.Get(pi1).unconditional) + { + hsp.Elem(pi1).unconditional = 1; + for (i = 1; i <= hsp.Size(); i++) + if (i != pi1 && Dist (hsp.Get(pi1).p, hsp.Get(i).p) < 1e-8 && + (hsp.Get(pi1).v + hsp.Get(i).v).Length() < 1e-4) + { + // opposite direction + hsp.Elem(i).unconditional = 1; + } + } + + cntedge++; + startpoints.Append (hsp.Get(pi1)); + +#ifdef DEVELOP + (*testout) << "edge nr " << cntedge << endl; + (*testout) << "start followedge: p1 = " << hsp.Get(pi1).p << ", v = " << 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); + continue; + } + + + + endpoints.Append (hsp.Get(ep)); + + + double elen = 0; + for (i = 1; i <= edgepoints.Size()-1; i++) + elen += Dist (edgepoints.Get(i), edgepoints.Get(i+1)); + + + int shortedge = 0; + for (i = 1; i <= geometry.identifications.Size(); i++) + if (geometry.identifications.Get(i)->ShortEdge(hsp.Get(pi1), hsp.Get(ep))) + shortedge = 1; + (*testout) << "shortedge = " << shortedge << endl; + + + if (!shortedge) + { + mesh.RestrictLocalHLine (Point3d (hsp.Get(pi1).p), + Point3d (hsp.Get(ep).p), + elen / mparam.segmentsperedge); + } + + s1 = hsp.Get(pi1).s1; + s2 = hsp.Get(pi1).s2; + + + // delete initial, terminal and conditional points + +#ifdef DEVELOP + (*testout) << "terminal point: p = " << hsp.Get(ep).p << ", v = " << hsp.Get(ep).v << endl; +#endif + if (ep > pi1) + { + hsp.DeleteElement (ep); + hsp.DeleteElement (pi1); + } + else + { + hsp.DeleteElement (pi1); + hsp.DeleteElement (ep); + } + + + for (j = 1; j <= edgepoints.Size()-1; j++) + { + p = edgepoints.Get(j); + np = Center (p, edgepoints.Get(j+1)); + hd = Dist2 (p, np); + + for (i = 1; i <= hsp.Size(); i++) + if ( hsp.Get(i).HasSurfaces (s1, s2) && + hsp.Get(i).unconditional == 0 && + Dist2 (np, hsp.Get(i).p) < 1.2 * hd) + { + hsp.DeleteElement (i); + i--; + } + } + + + ARRAY<Segment> refedges; + ARRAY<int> refedgesinv; + + + AnalyzeEdge (s1, s2, pos, layer, + edgepoints, + refedges, refedgesinv); + + for (i = 1; i <= refedges.Size(); i++) + refedges.Elem(i).edgenr = cntedge; + + +#ifdef DEVELOP + (*testout) << "edge " << cntedge << endl + << "startp: " << startpoints.Last().p + << ", v = " << startpoints.Last().v << endl + << "copy = " << copyedge << endl + << refedges.Size() << " refedges: "; + for (i = 1; i <= refedges.Size(); i++) + (*testout) << " " << refedges.Get(i).si; + (*testout) << endl; + (*testout) << "inv[1] = " << refedgesinv.Get(1) << endl; +#endif + + if (!copyedge) + { + int oldnseg = mesh.GetNSeg(); + + if (!shortedge) + StoreEdge (refedges, refedgesinv, + edgepoints, curvelength, layer, mesh); + else + StoreShortEdge (refedges, refedgesinv, + edgepoints, curvelength, layer, mesh); + + + /* + for (i = oldnseg+1; i <= mesh.GetNSeg(); i++) + for (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, + startpoints.Get(copyfromedge).p, + endpoints.Get(copyfromedge).p, + edgepoints.Get(1), edgepoints.Last(), + copyedgeidentification, + layer, + mesh); + } + + } + } + + + + /* + 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, k; + 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 (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.p1, seg.p2); + 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 ! + + for (i = 1; i <= osedgesht.GetNBags(); i++) + for (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) + { + PrintSysError ("Point on edge !!!"); + cout << "seg: " << i2 << ", p = " << k << endl; + osedgesht.Set (i2, 2); + } + } + } + } + + + // 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.p1, seg.p2); + i2.Sort (); + if (osedgesht.Used (i2) && + osedgesht.Get (i2) == 2 && + osedges.Elem(seg.edgenr) == -1) + { + Point<3> newp = Center (mesh[PointIndex(seg.p1)], + mesh[PointIndex(seg.p2)]); + + ProjectToEdge (geometry.GetSurface(seg.surfnr1), + geometry.GetSurface(seg.surfnr2), + newp); + + osedges.Elem(seg.edgenr) = + mesh.AddPoint (newp, mesh[PointIndex(seg.p1)].GetLayer()); + } + } + } + + + for (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.p1 = osedges.Get(seg.edgenr); + seg.p2 = osedges.Get(seg.edgenr); + mesh.AddSegment (newseg); + } + } + } + + } + + + + void EdgeCalculation :: + FollowEdge (int pi1, int & ep, int & pos, + const ARRAY<SpecialPoint> & hsp, + double h, const Mesh & mesh, + ARRAY<Point<3> > & edgepoints, + ARRAY<double> & curvelength) + { + int i, j, s1, s2; + double len, steplen, cursteplen, loch; + Point<3> p, np, pnp; + Vec<3> a1, a2, t; + + + double size = geometry.MaxSize(); // globflags.GetNumFlag ("maxsize", 500); + double epspointdist2 = size * 1e-6; // globflags.GetNumFlag ("epspointdist", size * 1e-6); + epspointdist2 = sqr (epspointdist2); + int uselocalh = mparam.uselocalh; + + + + s1 = hsp.Get(pi1).s1; + s2 = hsp.Get(pi1).s2; + + p = hsp.Get(pi1).p; + geometry.GetSurface(s1) -> CalcGradient (p, a1); + geometry.GetSurface(s2) -> CalcGradient (p, a2); + + t = Cross (a1, a2); + t.Normalize(); + + pos = (hsp.Get(pi1).v * t) > 0; + if (!pos) t *= -1; + + + edgepoints.Append (p); + curvelength.Append (0); + len = 0; + + 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); + if (lh < loch) + loch = lh; + } + + steplen = 0.1 * loch; + + do + { + if (multithread.terminate) + return; + + if (fabs (p(0)) + fabs (p(1)) + fabs (p(2)) > 10000) + { + 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; + +#ifdef MYGRAPH + if (silentflag <= 2) + { + MyLine3D (p, np, rot); + MyDraw (); + } +#endif + + 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)); + + for (i = 1; i <= hsp.Size(); i++) + // if ( i != pi1 && hsp[i].HasSurfaces (s1, s2) ) + { + if (!boxp.IsIn (hsp.Get(i).p)) + continue; + + Vec<3> hv = hsp.Get(i).p - p; + if (hv.Length2() > 9 * cursteplen * cursteplen) + continue; + /* + if (!hsp.Get(i).HasSurfaces (s1, s2)) + continue; // test for dalibor-problem + */ + double hvt = hv * t; + hv -= hvt * t; + + if (hv.Length() < 0.2 * cursteplen && + hvt > 0 && + // hvt < 1.5 * cursteplen && + hvt < hvtmin && + hsp.Get(i).unconditional == 1 && + (hsp.Get(i).v + t).Length() < 0.4 ) + { + Point<3> hep = hsp.Get(i).p; + ProjectToEdge (geometry.GetSurface(s1), + geometry.GetSurface(s2), hep); + + + if (Dist2 (hep, 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 ( (hsp.Get(i).v + ept).Length() < 1e-4 ) + { + np = hsp.Get(i).p; + ep = i; + hvtmin = hvt; + // break; + } + } + } + } + + loch = min2 (geometry.GetSurface(s1) -> LocH (np, 3, 1, h), + geometry.GetSurface(s2) -> LocH (np, 3, 1, h)); + + 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 pos, int layer, + const ARRAY<Point<3> > & edgepoints, + ARRAY<Segment> & refedges, + ARRAY<int> & refedgesinv) + { + int i, j, k, l; + int hi; + Point<3> hp; + Vec<3> t, a1, a2, m, n; + Segment seg; + Solid * locsol; + ARRAY<int> locsurfind; + + /* + int pi1 = 0, pi2 = 0; + extern Mesh * mesh; + for (i = 1; i <= mesh->GetNP(); i++) + { + if (Dist2 (edgepoints.Get(1), mesh->Point(i)) < 1e-12) + pi1 = i; + if (Dist2 (edgepoints.Last(), mesh->Point(i)) < 1e-12) + pi2 = i; + } + (*testout) << "Analyze edge: " << pi1 << " - " << pi2 << ", pts = " << edgepoints.Size() << endl; + (*testout) << "p1 = " << edgepoints.Get(1) << " pl = " << edgepoints.Last() << endl; + */ + int debug = 0; + /* + Dist2 (Point<3> (2.69642, 1.1866, 2.03), edgepoints.Get(1)) < 1e-6 || + Dist2 (Point<3> (2.69642, 1.1866, 2.03), edgepoints.Last()) < 1e-6; + */ + + if (debug) + { + // (*testout) << "tubious edge !!!" << endl; + (*testout) << "s1, s2 = " << s1 << " - " << s2 << endl; + } + + refedges.SetSize(0); + refedgesinv.SetSize(0); + hp = Center (edgepoints.Get(1), edgepoints.Get(2)); + ProjectToEdge (geometry.GetSurface(s1), geometry.GetSurface(s2), hp); + + geometry.GetSurface(s1) -> CalcGradient (hp, a1); + geometry.GetSurface(s2) -> CalcGradient (hp, a2); + t = Cross (a1, a2); + t.Normalize(); + if (!pos) t *= -1; + + (*testout) << "t = " << t << endl; + + for (i = 0; i < geometry.GetNTopLevelObjects(); i++) + { + (*testout) << "layer = " << layer + << ", tlo-layer = " << geometry.GetTopLevelObject(i)->GetLayer() << endl; + 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); + if (!locsol) continue; + + BoxSphere<3> boxp (hp, hp); + boxp.Increase (1e-5); + boxp.CalcDiamCenter(); + + ReducePrimitiveIterator rpi(boxp); + UnReducePrimitiveIterator urpi; + + ((Solid*)locsol) -> IterateSolid (rpi); + + locsol -> CalcSurfaceInverse (); + + + if (!surf) + { + locsol -> GetSurfaceIndices (locsurfind); + } + else + { + /* + if (fabs (surf->CalcFunctionValue (hp)) < 1e-6) + continue; + */ + locsurfind.SetSize(1); + locsurfind[0] = -1; + for (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 (j = locsurfind.Size()-1; j >= 0; j--) + if (fabs (geometry.GetSurface(locsurfind[j]) + ->CalcFunctionValue (hp) ) > 1e-6) + locsurfind.DeleteElement(j+1); + + if (debug) + (*testout) << locsurfind.Size() << " faces on hp" << endl; + + for (j = 0; j < locsurfind.Size(); j++) + { + int lsi = locsurfind[j]; + int rlsi = geometry.GetSurfaceClassRepresentant(lsi); + + Vec<3> rn; + + // n is outer normal to solid + geometry.GetSurface(lsi) -> GetNormalVector (hp, n); + if (geometry.GetSurface (lsi)->Inverse()) + n *= -1; + + if (fabs (t * n) > 1e-4) continue; + if (debug) + { + (*testout) << "face " << locsurfind.Get(j) << ", rep = " << rlsi + << " has (t*n) = " << (t*n) << endl; + (*testout) << "n = " << n << endl; + } + + // rn is normal to class representant + geometry.GetSurface(rlsi) -> GetNormalVector (hp, rn); + + int sameasref = ((n * rn) > 0); + + m = Cross (t, rn); + m.Normalize(); + + + for (k = 1; k <= 2; k ++) + { + bool edgeinv = (k == 2); + + if (debug) + { + (*testout) << "onface(" << hp << ", " << m << ")= " + << locsol->OnFace (hp, m); + (*testout) << " vec2in = " + << locsol -> VectorIn2 (hp, m, n) << " and " + << locsol -> VectorIn2 (hp, m, -1 * n) << endl; + } + + // if (locsol -> OnFace (hp, m)) + if (locsol -> VectorIn2 (hp, m, n) == 0 && + locsol -> VectorIn2 (hp, m, -1 * n) == 1) + { + hi = 0; + for (l = 1; l <= refedges.Size(); l++) + { + if (refedges.Get(l).si == rlsi && + refedgesinv.Get(l) == edgeinv) + hi = l; + } + + if (!hi) + { + seg.si = rlsi; + seg.domin = -1; + seg.domout = -1; + seg.tlosurf = -1; + seg.surfnr1 = s1; + seg.surfnr2 = s2; + hi = refedges.Append (seg); + refedgesinv.Append (edgeinv); + } + + if (!surf) + { + if (sameasref) + refedges.Elem(hi).domin = i; + else + refedges.Elem(hi).domout = i; + } + else + refedges.Elem(hi).tlosurf = i; + + 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 + << endl; + } + m *= -1; + } + } + delete locsol; + } + } + + + + void EdgeCalculation :: + StoreEdge (const ARRAY<Segment> & refedges, + const ARRAY<int> & 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); + + len = curvelength.Last(); + ne = int (len + 0.5); + if (ne == 0) ne = 1; + if (Dist2 (edgepoints.Get(1), edgepoints.Last()) < 1e-8 && + 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; + } + + if (lastpi == -1) + lastpi = mesh.AddPoint (p, layer); + + + 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; + + if (thispi == -1) + { + ProjectToEdge (surf1, surf2, np); + thispi = mesh.AddPoint (np, layer); + } + + for (k = 1; k <= refedges.Size(); k++) + { + if (refedgesinv.Get(k)) + { + seg.p1 = lastpi; + seg.p2 = thispi; + } + else + { + seg.p1 = thispi; + seg.p2 = 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 " << seg.p1 << "-" << seg.p2 << 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<int> & 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; + 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) + { + pi1 = pi; + break; + } + + if (pi1 == -1) pi1 = mesh.AddPoint (p, layer); + + p = edgepoints.Last(); + PointIndex pi2 = -1; + for (pi = PointIndex::BASE; + pi < mesh.GetNP()+PointIndex::BASE; pi++) + + if (Dist (mesh[pi], p) < 1e-6) + { + pi2 = pi; + break; + } + if (pi2==-1) pi2 = mesh.AddPoint (p, layer); + + /* + + 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); + } + */ + + for (k = 1; k <= refedges.Size(); k++) + { + if (refedgesinv.Get(k)) + { + seg.p1 = pi1; + seg.p2 = pi2; + } + else + { + seg.p1 = pi2; + seg.p2 = 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.p1 << "-" << seg.p2 << endl; + } + } + + + + + + + + void EdgeCalculation :: + CopyEdge (const ARRAY<Segment> & refedges, + const ARRAY<int> & 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 i, j, k; + PointIndex pi; + + // copy start and end points + for (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) + frompi = pi; + if (Dist2 (mesh[pi], top) <= 1e-16) + topi = pi; + } + + if (topi == -1) + topi = mesh.AddPoint (top, layer); + + 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); + } + /* + (*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 (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.p1; + int pi2 = oldseg.p2; + + int npi1 = geometry.identifications.Get(copyedgeidentification) + -> GetIdentifiedPoint (mesh, pi1); + int npi2 = geometry.identifications.Get(copyedgeidentification) + -> GetIdentifiedPoint (mesh, pi2); + + Segment seg; + + for (k = 1; k <= refedges.Size(); k++) + { + int inv = refedgesinv.Get(k); + + // other edge is inverse + if (oldseg.seginfo == 1) + inv = !inv; + + // (*testout) << "inv, now = " << inv << endl; + + if (inv) + { + seg.p1 = npi1; + seg.p2 = npi2; + } + else + { + seg.p1 = npi2; + seg.p2 = 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.p1 << "-" << seg.p2 << endl; +#ifdef DEVELOP + + (*testout) << "copy seg, face = " << seg.si << ": " + << " inv = " << inv << ", refinv = " << refedgesinv.Get(k) + << mesh.Point(seg.p1) << ", " << mesh.Point(seg.p2) << 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; + + BitArray pointatsurface (nsurf); + Point<3> p1, p2; + Vec<3> nv, tv; + Solid * tansol; + ARRAY<int> tansurfind; + // const Solid * sol; + + 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(); + s -> GetNormalVector (p1, nv); + + 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; + + for (j = 0; j < nsol; j++) + { + if (geometry.GetTopLevelObject(j)->GetSurface()) + continue; + + const Solid * sol = geometry.GetTopLevelObject(j)->GetSolid(); + sol -> TangentialSolid (p1, tansol); + 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); + mesh.AddPoint (p2, layer); + seg1.p1 = mesh.GetNP()-1; + seg1.p2 = mesh.GetNP(); + seg2.p2 = mesh.GetNP()-1; + seg2.p1 = 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/Netgen/libsrc/csg/edgeflw.hpp b/Netgen/libsrc/csg/edgeflw.hpp new file mode 100644 index 0000000000..175d2f164d --- /dev/null +++ b/Netgen/libsrc/csg/edgeflw.hpp @@ -0,0 +1,90 @@ +#ifndef FILE_EDGEFLW +#define FILE_EDGEFLW + +/**************************************************************************/ +/* File: edgeflw.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Okt. 95 */ +/**************************************************************************/ + +/* + + 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; + const ARRAY<SpecialPoint> & specpoints; + int cntedge; +public: + EdgeCalculation (const CSGeometry & ageometry, + const ARRAY<SpecialPoint> & aspecpoints); + + 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, + double h, const Mesh & mesh, + ARRAY<Point<3> > & edgepoints, + ARRAY<double> & curvelength); + + + void AnalyzeEdge (int s1, int s2, int pos, int layer, + const ARRAY<Point<3> > & edgepoints, + ARRAY<Segment> & refedges, + ARRAY<int> & refedgesinv); + + void StoreEdge (const ARRAY<Segment> & refedges, + const ARRAY<int> & refedgesinv, + const ARRAY<Point<3> > & edgepoints, + const ARRAY<double> & curvelength, + int layer, + Mesh & mesh); + + void StoreShortEdge (const ARRAY<Segment> & refedges, + const ARRAY<int> & refedgesinv, + const ARRAY<Point<3> > & edgepoints, + const ARRAY<double> & curvelength, + int layer, + Mesh & mesh); + + void CopyEdge (const ARRAY<Segment> & refedges, + const ARRAY<int> & 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); + +}; + + + +#endif diff --git a/Netgen/libsrc/csg/explicitcurve2d.cpp b/Netgen/libsrc/csg/explicitcurve2d.cpp new file mode 100644 index 0000000000..b1eef537c8 --- /dev/null +++ b/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; + 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/Netgen/libsrc/csg/explicitcurve2d.hpp b/Netgen/libsrc/csg/explicitcurve2d.hpp new file mode 100644 index 0000000000..af405aed3c --- /dev/null +++ b/Netgen/libsrc/csg/explicitcurve2d.hpp @@ -0,0 +1,109 @@ +#ifndef FILE_EXPLICITCURVE2D +#define FILE_EXPLICITCURVE2D + +/**************************************************************************/ +/* File: explicitcurve2d.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 14. Oct. 96 */ +/**************************************************************************/ + +/* + + 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/Netgen/libsrc/csg/extrusion.cpp b/Netgen/libsrc/csg/extrusion.cpp new file mode 100644 index 0000000000..acf9b863bc --- /dev/null +++ b/Netgen/libsrc/csg/extrusion.cpp @@ -0,0 +1,175 @@ +#include <mystdlib.h> + +#include <linalg.hpp> +#include <csg.hpp> + +namespace netgen +{ + + + + ExtrusionSurface :: ExtrusionSurface (const Point<3> & ap0, + const Vec<3> & aex, + const Vec<3> & aey, + BSplineCurve2d * acurve, + int asegnr) + : p0(ap0), ex(aex), ey(aey), curve(acurve), segnr(asegnr) + { + ; + } + + ExtrusionSurface :: ~ExtrusionSurface () + { + ; + } + + void ExtrusionSurface :: DefineTangentialPlane (const Point<3> & ap1, + const Point<3> & ap2) + { + ; + } + + void ExtrusionSurface :: ToPlane (const Point<3> & p3d, Point<2> & pplane, + double h, int & zone) const + { + ; + } + + void ExtrusionSurface :: FromPlane (const Point<2> & pplane, + Point<3> & p3d, double h) const + { + ; + } + + + void ExtrusionSurface :: Project (Point<3> & p) const + { + ; + } + + + double ExtrusionSurface :: CalcFunctionValue (const Point<3> & point) const + { + return 0; + } + + void ExtrusionSurface :: CalcGradient (const Point<3> & point, Vec<3> & grad) const + { + ; + } + + Point<3> ExtrusionSurface :: GetSurfacePoint () const + { + return Point<3> (0,0,0); + } + + double ExtrusionSurface :: HesseNorm () const + { + return 1; + } + + void ExtrusionSurface :: Print (ostream & str) const + { + ; + } + + void ExtrusionSurface :: GetTriangleApproximation (TriangleApproximation & tas, + const Box<3> & boundingbox, + double facets) const + { + Point<2> p2d; + Point<3> p; + int n = int(facets)+1; + Vec<3> ez = Cross (ex, ey); + cout << "ex = " << ex << endl; + cout << "ey = " << ey << endl; + for (double t = 0; t < 1.0001; t += 1.0 / n) + { + cout << "t = " << t << endl; + p2d = curve -> Eval (segnr+t); + p = p0 + p2d(0) * ex + p2d(1) * ey; + cout << "p2d = " << p2d << endl; + cout << "add point " << p << endl; + tas.AddPoint (p); + tas.AddPoint (p + ez); + } + + for (int i = 0; i < n; i++) + { + cout << "add trig " << endl; + tas.AddTriangle (TATriangle (0, 2*i, 2*i+2, 2*i+1)); + tas.AddTriangle (TATriangle (0, 2*i+2, 2*i+3, 2*i+1)); + } + } + + + + +Extrusion :: Extrusion (const Point<3> & ap0, + const Vec<3> & aex, + const Vec<3> & aey, + const ARRAY< Point<2> > & points) + : p0(ap0), ex(aex), ey(aey) +{ + int i; + + ex.Normalize(); + ey -= (ex*ey) * ex; + ey.Normalize(); + + for (i = 0; i < points.Size(); i++) + curve.AddPoint (points[i]); + + surfs.SetSize (points.Size()/2); + for (i = 0; i < surfs.Size(); i++) + surfs = new ExtrusionSurface (p0, ex, ey, &curve, i); +} + +Extrusion :: ~Extrusion () +{ + int i; + for (i = 0; i < surfs.Size(); i++) + delete surfs[i]; +} + + +INSOLID_TYPE Extrusion :: BoxInSolid (const BoxSphere<3> & box) const +{ + Vec<3> p0c = box.Center() - p0; + Point<2> p2d (ex*p0c, ey*p0c); + double r = box.Diam() / 2; + double dist; + bool inside = + curve.Inside (p2d, dist); + + if (inside && dist > r) return IS_INSIDE; + if (!inside && dist > r) return IS_OUTSIDE; + return DOES_INTERSECT; +} + + +INSOLID_TYPE Extrusion :: PointInSolid (const Point<3> & p, + double eps) const +{ + Vec<3> p0c = p - p0; + Point<2> p2d (ex*p0c, ey*p0c); + double dist; + bool inside = + curve.Inside (p2d, dist); + + if (dist < eps) return DOES_INTERSECT; + if (inside) return IS_INSIDE; + return IS_OUTSIDE; +} + + +INSOLID_TYPE Extrusion :: VecInSolid (const Point<3> & p, + const Vec<3> & v, + double eps) const +{ + Point<3> p2 = p + (1e-3/(v.Length()+1e-16)) * v; + return PointInSolid (p2, eps); +} + + +} diff --git a/Netgen/libsrc/csg/extrusion.hpp b/Netgen/libsrc/csg/extrusion.hpp new file mode 100644 index 0000000000..ff5a47b4e1 --- /dev/null +++ b/Netgen/libsrc/csg/extrusion.hpp @@ -0,0 +1,89 @@ +#ifndef FILE_EXTRUSION +#define FILE_EXTRUSION + +/**************************************************************************/ +/* File: extrusion.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 17. Mar. 2003 */ +/**************************************************************************/ + +/* + +extrusion of 2D curve + +*/ + + +class ExtrusionSurface : public Surface +{ +protected: + BSplineCurve2d * curve; + int segnr; + Point<3> p0; + Vec<3> ex, ey; +public: + ExtrusionSurface (const Point<3> & ap0, + const Vec<3> & aex, + const Vec<3> & aey, + BSplineCurve2d * acurve, + int asegnr); + virtual ~ExtrusionSurface (); + + 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 double CalcFunctionValue (const Point<3> & point) const; + + virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const; + + virtual Point<3> GetSurfacePoint () const; + + virtual double HesseNorm () const; + + virtual void Print (ostream & str) const; + virtual void GetTriangleApproximation (TriangleApproximation & tas, + const Box<3> & boundingbox, + double facets) const; +}; + + +class Extrusion : public Primitive +{ +protected: + Point<3> p0; + Vec<3> ex, ey; + BSplineCurve2d curve; + ARRAY<ExtrusionSurface*> surfs; + +public: + Extrusion (const Point<3> & ap0, + const Vec<3> & aex, + const Vec<3> & aey, + const ARRAY< Point<2> > & points); + virtual ~Extrusion (); + + + + 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 int GetNSurfaces() const { return surfs.Size(); } + virtual Surface & GetSurface (int i) { return *surfs[i]; } + virtual const Surface & GetSurface (int i) const { return *surfs[i]; } +}; + +#endif diff --git a/Netgen/libsrc/csg/gencyl.cpp b/Netgen/libsrc/csg/gencyl.cpp new file mode 100644 index 0000000000..f079879738 --- /dev/null +++ b/Netgen/libsrc/csg/gencyl.cpp @@ -0,0 +1,209 @@ +#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(1, 1) = (1 - curvpp(0) * curvpp(0) ) / dist; + h2d(1, 2) = h2d(2, 1) = (- curvpp(0) * curvpp(1) ) / dist; + h2d(2, 2) = (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); +} + +#ifdef MYGRAPH +void GeneralizedCylinder :: Plot (const class ROT3D & rot) const +{ + Point<2> p2d; + Point<3> p, oldp; + double t, tmin, tmax, dt; + + tmin = crosssection.MinParam(); + tmax = crosssection.MaxParam(); + dt = (tmax - tmin)/ 500; + + p2d = crosssection.Eval(tmin); + p = planep + p2d(0) * planee1 + p2d(1) * planee2; + + for (t = tmin; t <= tmax+dt; t += dt) + { + if (crosssection.SectionUsed (t)) + MySetColor (RED); + else + MySetColor (BLUE); + + oldp = p; + p2d = crosssection.Eval(t); + p = planep + p2d(0) * planee1 + p2d(1) * planee2; + MyLine3D (p, oldp, rot); + } + +} + +#endif +} diff --git a/Netgen/libsrc/csg/gencyl.hpp b/Netgen/libsrc/csg/gencyl.hpp new file mode 100644 index 0000000000..424c867a92 --- /dev/null +++ b/Netgen/libsrc/csg/gencyl.hpp @@ -0,0 +1,64 @@ +#ifndef FILE_GENCYL +#define FILE_GENCYL + +/**************************************************************************/ +/* File: gencyl.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 14. Oct. 96 */ +/**************************************************************************/ + +/* + + 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/Netgen/libsrc/csg/genmesh.cpp b/Netgen/libsrc/csg/genmesh.cpp new file mode 100644 index 0000000000..62a336e260 --- /dev/null +++ b/Netgen/libsrc/csg/genmesh.cpp @@ -0,0 +1,709 @@ +#include <mystdlib.h> + + +// #include <FlexLexer.h> + +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> +#include <stlgeom.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, + const char * filename) +{ + int i; + PrintMessage (1, "Start Findpoints"); + + char * savetask = multithread.task; + multithread.task = "Find points"; + + for (i = 0; i < geom.GetNUserPoints(); i++) + { + mesh.AddPoint (geom.GetUserPoint (i)); + mesh.AddLockedPoint (PointIndex (i+1)); + } + + SpecialPointCalculation spc; + + 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 (i = 0; i < specpoints.Size(); i++) + specpoints[i].Print (*testout); + + /* + for (i = 1; i <= geom.identifications.Size(); i++) + geom.identifications.Elem(i)->IdentifySpecialPoints (specpoints); + */ + multithread.task = savetask; +} + + + +static void FindEdges (CSGeometry & geom, Mesh & mesh, + const char * filename) +{ + int i, k; + + EdgeCalculation ec (geom, specpoints); + ec.Calc (mparam.maxh, mesh); + + for (i = 1; i <= geom.singedges.Size(); i++) + geom.singedges.Elem(i)->FindPointsOnEdge (mesh); + for (i = 1; i <= geom.singpoints.Size(); i++) + geom.singpoints.Elem(i)->FindPoints (mesh); + + // SaveEdges (mesh, filename, h, "edges.out"); + + for (i = 1; i <= mesh.GetNSeg(); i++) + { + int ok = 0; + for (k = 1; k <= mesh.GetNFD(); k++) + if (mesh.GetFaceDescriptor(k).SegmentFits (mesh.LineSegment(i))) + ok = k; + + if (!ok) + ok = mesh.AddFaceDescriptor (FaceDescriptor (mesh.LineSegment(i))); + + mesh.LineSegment(i).si = ok; + } + + (*testout) << "identify points after line meshing" << endl; + for (i = 0; i < geom.identifications.Size(); i++) + geom.identifications[i]->IdentifyPoints (mesh); + for (i = 0; i < geom.identifications.Size(); i++) + geom.identifications[i]->IdentifyFaces (mesh); + + // mesh.Save ("lines.vol"); +} + + +static void MeshSurface (CSGeometry & geom, Mesh & mesh) +{ + int i, j, k; + int changed; + + 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 (i = 1; i <= mesh.GetNFD(); i++) + masterface.Elem(i) = i; + + ARRAY<INDEX_2> fpairs; + do + { + changed = 0; + for (i = 0; i < geom.identifications.Size(); i++) + { + geom.identifications[i]->GetIdentifiedFaces (fpairs); + + for (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 (k = 0; k < geom.GetNSurf(); k++) + bccnt = max2 (bccnt, geom.GetSurface(k)->GetBCProperty()); + + for (k = 1; k <= mesh.GetNFD(); k++) + { + 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); + } + + 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)) + { + cout << "modify, surfnr = " << fd.SurfNr() << ", dom = " + << geom.bcmodifications[l].tlonr+1 << endl; + fd.SetBCProperty (geom.bcmodifications[l].bcnr); + } + } + } + + /* + (*testout) << "Face descriptors:" << endl; + for (k = 1; k <= mesh.GetNFD(); k++) + (*testout) << "fd(" << k << ") = " << mesh.GetFaceDescriptor(k) << endl; + */ + + // assemble edge hash-table + (*testout) << "calc surf before surface" << endl; + mesh.CalcSurfacesOfNode(); + + for (k = 1; k <= mesh.GetNFD(); k++) + { + (*testout) << "mesh face " << k << endl; + multithread.percent = 100 * 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())); + + /* + if (surf -> GetBCProperty() != -1) + fd.SetBCProperty (surf->GetBCProperty()); + else + { + bccnt++; + fd.SetBCProperty (bccnt); + } + */ + + + Meshing2Surfaces meshing(*surf, geom.BoundingBox()); + meshing.SetStartTime (starttime); + + for (PointIndex pi = PointIndex::BASE; + pi < noldp+PointIndex::BASE; pi++) + { + meshing.AddPoint (mesh[pi], pi); + } + + segments.SetSize (0); + + for (i = 1; i <= mesh.GetNSeg(); i++) + { + Segment * seg = &mesh.LineSegment(i); + if (seg->si == k) + { + segments.Append (*seg); + (*testout) << "add segment " << seg->p1 << "-" << seg->p2 << endl; + } + } + + for (i = 1; i <= geom.identifications.Size(); i++) + geom.identifications.Get(i)-> + BuildSurfaceElements(segments, mesh, surf); + + // (*testout) << "Mesh surface, elements:" << endl; + for (SegmentIndex si = 0; si < segments.Size(); si++) + { + PointGeomInfo gi; + gi.trignum = k; + /* + (*testout) << segments[si].p1 << " - " << segments[si].p2 << endl; + (*testout) << mesh[segments[si].p1] << " - " + << mesh[segments[si].p2] << endl; + */ + meshing.AddBoundaryElement (segments[si].p1 + 1 - PointIndex::BASE, + segments[si].p2 + 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; + + + MESHING2_RESULT res = + meshing.GenerateMesh (mesh, maxh, k); + + if (res != MESHING2_OK) + { + PrintError ("Problem in Surface mesh generation"); + throw NgException ("Problem in Surface mesh generation"); + } + if (multithread.terminate) return; + + + for (i = oldnf+1; i <= mesh.GetNSE(); i++) + mesh.SurfaceElement(i).SetIndex (k); + + + // mesh.CalcSurfacesOfNode(); + if (segments.Size()) + { + // surface was meshed, not copied + PrintMessage (2, "Optimize Surface"); + for (i = 1; i <= mparam.optsteps2d; i++) + { + if (multithread.terminate) return; + + { + MeshOptimize2dSurfaces meshopt(geom); + meshopt.SetFaceIndex (k); + meshopt.SetImproveEdges (0); + meshopt.SetMetricWeight (0.2); + 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 (0.2); + meshopt.SetWriteStatus (0); + + meshopt.ImproveMesh (mesh); + } + + { + MeshOptimize2dSurfaces meshopt(geom); + meshopt.SetFaceIndex (k); + meshopt.SetImproveEdges (0); + meshopt.SetMetricWeight (0.2); + meshopt.SetWriteStatus (0); + + meshopt.CombineImprove (mesh); + // mesh.CalcSurfacesOfNode(); + } + + if (multithread.terminate) return; + { + MeshOptimize2dSurfaces meshopt(geom); + meshopt.SetFaceIndex (k); + meshopt.SetImproveEdges (0); + meshopt.SetMetricWeight (0.2); + meshopt.SetWriteStatus (0); + + meshopt.ImproveMesh (mesh); + } + } + } + + + + PrintMessage (3, (mesh.GetNSE() - oldnf), " elements, ", mesh.GetNP(), " points"); + +#ifdef OPENGL + extern void Render(); + Render(); +#endif + } + + mesh.Compress(); + + + + + + + + do + { + changed = 0; + for (k = 1; k <= mesh.GetNFD(); k++) + { + multithread.percent = 100 * 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 (i = 1; i <= mesh.GetNSeg(); i++) + { + Segment * seg = &mesh.LineSegment(i); + if (seg->si == k) + segments.Append (*seg); + } + + for (i = 1; i <= geom.identifications.Size(); i++) + { + geom.identifications.Elem(i)->GetIdentifiedFaces (fpairs); + int found = 0; + for (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 (i = oldnf+1; i <= mesh.GetNSE(); i++) + mesh.SurfaceElement(i).SetIndex (k); + + + if (!segments.Size()) + { + masterface.Elem(k) = k; + changed = 1; + } + + PrintMessage (3, (mesh.GetNSE() - oldnf), " elements, ", mesh.GetNP(), " points"); + } + +#ifdef OPENGL + extern void Render(); + Render(); +#endif + } + while (changed); + + mesh.SplitSeparatedFaces(); + + mesh.CalcSurfacesOfNode(); + + multithread.task = savetask; +} + + +int GenerateMesh (CSGeometry & geom, + Mesh *& mesh, + int perfstepsstart, int perfstepsend, + const char * optstr) +{ + extern char geomfilename[]; + const char * filename = geomfilename; + + int i; + char filenametrunc[255]; + char filenameext[255]; + + if (mesh && mesh->GetNSE() && + !geom.GetNSolids()) + { + if (perfstepsstart < MESHCONST_MESHVOLUME) + perfstepsstart = MESHCONST_MESHVOLUME; + } + + + + strcpy (filenametrunc, filename); + char * pos = strstr (filenametrunc, ".geo"); + if (pos) strcpy (pos, ""); + + if (perfstepsstart <= MESHCONST_ANALYSE) + { + delete mesh; + mesh = new Mesh(); + + mesh->SetGlobalH (mparam.maxh); + + ARRAY<double> maxhdom(geom.GetNTopLevelObjects()); + for (i = 0; i < maxhdom.Size(); i++) + maxhdom[i] = geom.GetTopLevelObject(i)->GetMaxH(); + + mesh->SetMaxHDomain (maxhdom); + + if (mparam.uselocalh) + { + // double maxsize = globflags.GetNumFlag ("maxsize", 500); + double maxsize = geom.MaxSize(); + mesh->SetLocalH (Point<3>(-maxsize, -maxsize, -maxsize), + Point<3>(maxsize, maxsize, maxsize), + mparam.grading); + + if (mparam.meshsizefilename) + { + ifstream msf(mparam.meshsizefilename); + if (msf) + mesh->LoadLocalMeshSize (msf); + } + } + + spoints.SetSize(0); + FindPoints (geom, *mesh, filename); + + 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, filename); + 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(); + mesh->DeleteMesh(); + + FindPoints (geom, *mesh, filename); + if (multithread.terminate) return TCL_OK; + FindEdges (geom, *mesh, filename); + if (multithread.terminate) return TCL_OK; + + mesh->DeleteMesh(); + + FindPoints (geom, *mesh, filename); + if (multithread.terminate) return TCL_OK; + FindEdges (geom, *mesh, filename); + 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(); + mesh->DeleteMesh(); + + FindPoints (geom, *mesh, filename); + if (multithread.terminate) return TCL_OK; + FindEdges (geom, *mesh, filename); + 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(); + + /* + strcpy (filenameext, filenametrunc); + strcat (filenameext, ".surf.mesh"); + WriteFile (WRITE_SURFACE, mesh, geom, filenameext, filename, h); + */ + } + + 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, &geom); + 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 + + +#ifndef TRAFO + /* + if (&geom) + { + ZRefinementOptions opt; + opt.minref = 0; + ZRefinement (*mesh, &geom, opt); + } + */ +#endif + } + + /* + cout << (char)7 << (char)7 << endl; + cout << "Meshing finished" << endl << endl; + cout << setw (4) << mesh->GetNP() << " Points" << endl; + cout << setw (4) << mesh->GetNSE() << " Surface Elements" << endl; + cout << setw (4) << mesh->GetNE() << " Volume Elements" << endl; + cout << setw (4) << int (GetTime()) << " Seconds" << endl; + */ + + /* + strcpy (filenameext, filenametrunc); + strcat (filenameext, ".vol"); + mesh->Save (filenameext); + */ + + return TCL_OK; +} +} diff --git a/Netgen/libsrc/csg/geometry.cpp b/Netgen/libsrc/csg/geometry.cpp new file mode 100644 index 0000000000..14806ee9cb --- /dev/null +++ b/Netgen/libsrc/csg/geometry.cpp @@ -0,0 +1,1792 @@ +/* A Bison parser, made from geometry.yy + by GNU bison 1.35. */ + +#define YYBISON 1 /* Identify Bison output. */ + +# define NUM 257 +# define TOK_SOLID 258 +# define TOK_RECO 259 +# define TOK_TLO 260 +# define TOK_BOUNDINGBOX 261 +# define IDENT 262 +# define IDENTSOLID 263 +# define TOK_SPHERE 264 +# define TOK_CYLINDER 265 +# define TOK_CONE 266 +# define TOK_PLAIN 267 +# define TOK_TUBE 268 +# define TOK_GENCYL 269 +# define TOK_ORTHOBRICK 270 +# define TOK_POLYHEDRON 271 +# define TOK_REVOLUTION 272 +# define TOK_OR 273 +# define TOK_AND 274 +# define TOK_NOT 275 +# define TOK_TRANSLATE 276 +# define TOK_MULTITRANSLATE 277 +# define TOK_ROTATE 278 +# define TOK_MULTIROTATE 279 +# define TOK_SINGULAR 280 +# define TOK_EDGE 281 +# define TOK_POINT 282 +# define TOK_IDENTIFY 283 +# define TOK_CLOSESURFACES 284 +# define TOK_CLOSEEDGES 285 +# define TOK_PERIODIC 286 +# define TOK_BOUNDARYCONDITION 287 + +#line 1 "geometry.yy" + +//define YYDEBUG 1 + +extern int yylex (); + +#include <mystdlib.h> + +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> + +namespace netgen +{ +netgen::CSGeometry * parsegeom; +} + +using namespace netgen; + +// extern ARRAY<Surface*> surfaces; +// extern SYMBOLTABLE<Solid*> solids; + + +int yyerror (char * s); +splinetube * tube; +spline3d * middlecurve; +Point<3> splinep1; +BSplineCurve2d *bspline; +Flags parseflags; +extern int linenum; +ARRAY<double> doublearray; +ARRAY<char*> stringarray; + +Polyhedra * polyhedron; +// Revolution * revolution; + +#line 38 "geometry.yy" +#ifndef YYSTYPE +typedef union { +double val; +char * chptr; +Solid * solidtype; +} yystype; +# define YYSTYPE yystype +# define YYSTYPE_IS_TRIVIAL 1 +#endif +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + + + +#define YYFINAL 260 +#define YYFLAG -32768 +#define YYNTBASE 42 + +/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */ +#define YYTRANSLATE(x) ((unsigned)(x) <= 287 ? yytranslate[x] : 67) + +/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */ +static const char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 36, 37, 2, 2, 38, 39, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 34, + 2, 35, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 40, 2, 41, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33 +}; + +#if YYDEBUG +static const short yyprhs[] = +{ + 0, 0, 1, 6, 7, 11, 12, 19, 21, 23, + 27, 31, 34, 38, 49, 66, 85, 100, 115, 116, + 125, 136, 149, 166, 185, 189, 191, 195, 197, 203, + 209, 217, 221, 223, 227, 229, 233, 245, 246, 252, + 253, 254, 261, 262, 266, 272, 279, 285, 291, 296, + 300, 305, 320, 329, 334, 335, 338, 339, 342, 345, + 350, 355, 360, 365, 366, 371, 373, 377, 378, 383, + 385, 389, 391 +}; +static const short yyrhs[] = +{ + -1, 43, 5, 44, 54, 0, 0, 44, 45, 34, + 0, 0, 4, 8, 35, 47, 46, 56, 0, 48, + 0, 9, 0, 47, 19, 47, 0, 47, 20, 47, + 0, 21, 47, 0, 36, 47, 37, 0, 10, 36, + 3, 38, 3, 38, 3, 34, 3, 37, 0, 11, + 36, 3, 38, 3, 38, 3, 34, 3, 38, 3, + 38, 3, 34, 3, 37, 0, 12, 36, 3, 38, + 3, 38, 3, 34, 3, 34, 3, 38, 3, 38, + 3, 34, 3, 37, 0, 13, 36, 3, 38, 3, + 38, 3, 34, 3, 38, 3, 38, 3, 37, 0, + 16, 36, 3, 38, 3, 38, 3, 34, 3, 38, + 3, 38, 3, 37, 0, 0, 17, 36, 49, 50, + 34, 34, 51, 37, 0, 22, 36, 3, 38, 3, + 38, 3, 34, 47, 37, 0, 23, 36, 3, 38, + 3, 38, 3, 34, 3, 34, 47, 37, 0, 24, + 36, 3, 38, 3, 38, 3, 34, 3, 38, 3, + 38, 3, 34, 47, 37, 0, 25, 36, 3, 38, + 3, 38, 3, 34, 3, 38, 3, 38, 3, 34, + 3, 34, 47, 37, 0, 50, 34, 52, 0, 52, + 0, 51, 34, 53, 0, 53, 0, 3, 38, 3, + 38, 3, 0, 3, 38, 3, 38, 3, 0, 3, + 38, 3, 38, 3, 38, 3, 0, 67, 34, 68, + 0, 68, 0, 3, 38, 3, 0, 70, 0, 70, + 38, 69, 0, 3, 38, 3, 38, 3, 38, 3, + 38, 3, 38, 3, 0, 0, 3, 38, 3, 72, + 73, 0, 0, 0, 38, 3, 38, 3, 74, 73, + 0, 0, 54, 55, 34, 0, 26, 27, 3, 9, + 9, 0, 26, 28, 3, 9, 9, 9, 0, 29, + 30, 9, 9, 56, 0, 29, 31, 9, 9, 9, + 0, 29, 32, 9, 9, 0, 6, 9, 56, 0, + 6, 9, 9, 56, 0, 7, 36, 3, 38, 3, + 38, 3, 34, 3, 38, 3, 38, 3, 37, 0, + 28, 36, 3, 38, 3, 38, 3, 37, 0, 33, + 9, 9, 3, 0, 0, 57, 58, 0, 0, 59, + 58, 0, 39, 66, 0, 39, 66, 35, 66, 0, + 39, 66, 35, 3, 0, 39, 66, 35, 60, 0, + 39, 66, 35, 63, 0, 0, 40, 61, 62, 41, + 0, 3, 0, 62, 38, 3, 0, 0, 40, 64, + 65, 41, 0, 66, 0, 65, 38, 66, 0, 8, + 0, 9, 0 +}; + +#endif + +#if YYDEBUG +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const short yyrline[] = +{ + 0, 61, 61, 79, 81, 84, 84, 94, 96, 97, + 98, 99, 100, 103, 112, 123, 135, 144, 158, 158, + 197, 206, 222, 231, 285, 287, 289, 291, 293, 300, + 306, 315, 317, 319, 331, 333, 335, 345, 345, 354, + 356, 356, 372, 374, 377, 385, 394, 409, 425, 439, + 453, 470, 477, 482, 511, 511, 516, 518, 521, 524, + 526, 528, 530, 535, 535, 540, 542, 545, 545, 556, + 563, 574, 576 +}; +#endif + + +#if (YYDEBUG) || defined YYERROR_VERBOSE + +/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */ +static const char *const yytname[] = +{ + "$", "error", "$undefined.", "NUM", "TOK_SOLID", "TOK_RECO", "TOK_TLO", + "TOK_BOUNDINGBOX", "IDENT", "IDENTSOLID", "TOK_SPHERE", "TOK_CYLINDER", + "TOK_CONE", "TOK_PLAIN", "TOK_TUBE", "TOK_GENCYL", "TOK_ORTHOBRICK", + "TOK_POLYHEDRON", "TOK_REVOLUTION", "TOK_OR", "TOK_AND", "TOK_NOT", + "TOK_TRANSLATE", "TOK_MULTITRANSLATE", "TOK_ROTATE", "TOK_MULTIROTATE", + "TOK_SINGULAR", "TOK_EDGE", "TOK_POINT", "TOK_IDENTIFY", + "TOK_CLOSESURFACES", "TOK_CLOSEEDGES", "TOK_PERIODIC", + "TOK_BOUNDARYCONDITION", "';'", "'='", "'('", "')'", "','", "'-'", + "'['", "']'", "input", "@1", "recsoliddef", "soliddef", "@2", "solid", + "solidprimitive", "@3", "polyhedronpoints", "polyhedronfaces", + "polyhedronpoint", "polyhedronface", "recadddef", "adddef", "flaglist", + "@6", "recflaglist", "flag", "numlistbrack", "@7", "numlist", + "stringlistbrack", "@8", "stringlist", "anyident", 0 +}; +#endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const short yyr1[] = +{ + 0, 43, 42, 44, 44, 46, 45, 47, 47, 47, + 47, 47, 47, 48, 48, 48, 48, 48, 49, 48, + 48, 48, 48, 48, 50, 50, 51, 51, 52, 53, + 53, 67, 67, 68, 69, 69, 70, 72, 71, 73, + 74, 73, 54, 54, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 57, 56, 58, 58, 59, 59, + 59, 59, 59, 61, 60, 62, 62, 64, 63, 65, + 65, 66, 66 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const short yyr2[] = +{ + 0, 0, 4, 0, 3, 0, 6, 1, 1, 3, + 3, 2, 3, 10, 16, 18, 14, 14, 0, 8, + 10, 12, 16, 18, 3, 1, 3, 1, 5, 5, + 7, 3, 1, 3, 1, 3, 11, 0, 5, 0, + 0, 6, 0, 3, 5, 6, 5, 5, 4, 3, + 4, 14, 8, 4, 0, 2, 0, 2, 2, 4, + 4, 4, 4, 0, 4, 1, 3, 0, 4, 1, + 3, 1, 1 +}; + +/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE + doesn't specify something else to do. Zero means the default is an + error. */ +static const short yydefact[] = +{ + 1, 0, 3, 42, 0, 0, 2, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, + 0, 0, 0, 0, 0, 0, 43, 8, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 7, 54, 49, 56, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 18, 11, + 0, 0, 0, 0, 0, 0, 0, 54, 50, 0, + 55, 56, 0, 0, 0, 0, 54, 0, 48, 53, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 9, 10, 6, 71, 72, 58, 57, 0, 44, + 0, 0, 46, 47, 0, 0, 0, 0, 0, 0, + 0, 25, 0, 0, 0, 0, 0, 0, 45, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 60, 67, 61, 62, 59, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, + 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, + 0, 0, 27, 0, 0, 0, 0, 65, 0, 0, + 69, 0, 0, 0, 0, 0, 0, 28, 0, 0, + 19, 0, 0, 0, 0, 0, 64, 0, 68, 0, + 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, + 0, 66, 70, 0, 13, 0, 0, 0, 0, 0, + 20, 0, 0, 0, 0, 0, 0, 0, 0, 29, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, + 0, 0, 51, 0, 0, 0, 0, 30, 0, 0, + 0, 0, 16, 17, 0, 0, 0, 0, 0, 0, + 14, 0, 22, 0, 0, 0, 15, 23, 0, 0, + 0 +}; + +static const short yydefgoto[] = +{ + 258, 1, 3, 5, 67, 40, 41, 85, 110, 161, + 111, 162, 6, 15, 43, 44, 70, 71, 133, 150, + 168, 134, 151, 169, 96 +}; + +static const short yypact[] = +{ + -32768, 5,-32768, 18, 21, 7, 14, 11,-32768, 52, + 35, 36, 39, 28, 56, 42, 2, 58, 66, 74, + 75, 76, 71, 72, 73, 77,-32768,-32768, 48, 49, + 51, 53, 55, 57, 2, 59, 60, 61, 62, 2, + 54,-32768,-32768,-32768, 44, 50, 81, 83, 63, 85, + 90, 91, 99, 100, 101, 102, 103, 104,-32768,-32768, + 105, 106, 107, 108, -3, 2, 2,-32768,-32768, 47, + -32768, 44, 109, 110, 111, 112,-32768, 113,-32768,-32768, + 78, 79, 80, 86, 87, 118, 88, 89, 92, 93, + -32768,-32768,-32768,-32768,-32768,-32768, 94,-32768, 95,-32768, + 114, 96,-32768,-32768, 125, 129, 132, 133, 134, 115, + 116,-32768, 135, 136, 137, 138, -1, 139,-32768, 140, + 117, 119, 120, 121, 122, 141, 1, 123, 124, 126, + 127,-32768, 142,-32768,-32768,-32768, 144, 130, 143, 145, + 146, 148, 149, 128, 151,-32768, 153, 160, 165, 166, + 167, 47, 168,-32768, 147, 150, 152, 154, 155, 169, + 156, -28,-32768, 157, 158, 159, 161,-32768, -8, 16, + -32768, 162, 170, 171, 172, 173, 176,-32768, 177, 151, + -32768, 2, 179, 180, 182, 184,-32768, 47,-32768, 187, + 164, 174, 163, 175, 178, 183,-32768, 25, 181, 185, + 186,-32768,-32768, 188,-32768, 193, 195, 196, 199, 200, + -32768, 2, 201, 202, 203, 189, 190, 191, 192, 194, + 29, 197, 198, 204, 205, 206, 208, 211, 214,-32768, + 215, 217,-32768, 209, 207, 210, 212,-32768, 216, 218, + 219, 222,-32768,-32768, 2, 228, 220, 221, 31, 224, + -32768, 230,-32768, 2, 223, 33,-32768,-32768, 234, 237, + -32768 +}; + +static const short yypgoto[] = +{ + -32768,-32768,-32768,-32768,-32768, -34,-32768,-32768,-32768,-32768, + -13, -65,-32768,-32768, -39,-32768, 213,-32768,-32768,-32768, + -32768,-32768,-32768,-32768, -115 +}; + + +#define YYLAST 284 + + +static const short yytable[] = +{ + 59, 135, 131, 68, 109, 64, 179, 94, 95, 180, + 2, 27, 28, 29, 30, 31, 65, 66, 32, 33, + 9, 10, 4, 34, 35, 36, 37, 38, 93, 7, + 185, 91, 92, 186, 90, 144, 170, 102, 39, 132, + 11, 8, 12, 13, 65, 66, 16, 14, 65, 66, + 65, 66, 65, 66, 187, 94, 95, 188, 22, 23, + 24, 17, 210, 19, 20, 25, 229, 42, 252, 45, + 257, 18, 202, 65, 66, 21, 26, 46, 47, 48, + 49, 50, 51, 69, 53, 54, 52, 55, 72, 56, + 73, 57, 74, 58, 76, 60, 61, 62, 63, 77, + 78, 75, 79, 80, 81, 82, 83, 84, 86, 87, + 88, 89, 98, 145, 196, 101, 104, 105, 106, 99, + 100, 109, 103, 118, 107, 108, 112, 113, 120, 116, + 114, 115, 121, 117, 119, 122, 123, 124, 127, 128, + 129, 130, 136, 137, 143, -63, 154, 197, 155, 156, + 126, 157, 158, 125, 160, 138, 163, 139, 140, 141, + 142, 146, 147, 164, 148, 149, 159, 153, 165, 166, + 167, 171, 177, 190, 191, 192, 193, 220, 152, 194, + 195, 172, 198, 199, 173, 200, 174, 201, 175, 176, + 203, 181, 182, 183, 178, 184, 215, 206, 216, 217, + 189, 204, 218, 219, 221, 222, 223, 0, 233, 234, + 248, 235, 205, 207, 236, 211, 208, 237, 238, 255, + 239, 209, 246, 212, 213, 247, 214, 224, 225, 226, + 227, 249, 228, 254, 259, 230, 231, 260, 0, 0, + 0, 232, 0, 240, 0, 241, 0, 242, 0, 243, + 244, 0, 245, 0, 0, 251, 0, 250, 253, 0, + 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 97 +}; + +static const short yycheck[] = +{ + 34, 116, 3, 42, 3, 39, 34, 8, 9, 37, + 5, 9, 10, 11, 12, 13, 19, 20, 16, 17, + 6, 7, 4, 21, 22, 23, 24, 25, 67, 8, + 38, 65, 66, 41, 37, 34, 151, 76, 36, 40, + 26, 34, 28, 29, 19, 20, 35, 33, 19, 20, + 19, 20, 19, 20, 38, 8, 9, 41, 30, 31, + 32, 9, 37, 27, 28, 9, 37, 9, 37, 3, + 37, 36, 187, 19, 20, 36, 34, 3, 3, 3, + 9, 9, 9, 39, 36, 36, 9, 36, 38, 36, + 9, 36, 9, 36, 9, 36, 36, 36, 36, 9, + 9, 38, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 126, 179, 3, 38, 38, 38, 9, + 9, 3, 9, 9, 38, 38, 38, 38, 3, 35, + 38, 38, 3, 38, 38, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 181, 3, 3, + 34, 3, 3, 38, 3, 38, 3, 38, 38, 38, + 38, 38, 38, 3, 38, 38, 38, 37, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 211, 34, 3, + 3, 34, 3, 3, 34, 3, 34, 3, 34, 34, + 3, 34, 34, 34, 38, 34, 3, 34, 3, 3, + 38, 37, 3, 3, 3, 3, 3, -1, 3, 3, + 244, 3, 38, 38, 3, 34, 38, 3, 3, 253, + 3, 38, 3, 38, 38, 3, 38, 38, 38, 38, + 38, 3, 38, 3, 0, 38, 38, 0, -1, -1, + -1, 37, -1, 34, -1, 38, -1, 37, -1, 37, + 34, -1, 34, -1, -1, 34, -1, 37, 34, -1, + 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 71 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/share/bison/bison.simple" + +/* Skeleton output parser for bison, + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* This is the parser code that is written into each bison parser when + the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +#ifndef YYPARSE_RETURN_TYPE +#define YYPARSE_RETURN_TYPE int +#endif + +#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE) + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || ((YYLTYPE_IS_TRIVIAL || ! YYLSP_NEEDED) && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; +# if YYLSP_NEEDED + YYLTYPE yyls; +# endif +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# if YYLSP_NEEDED +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAX) +# else +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAX) +# endif + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up"); \ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). + + When YYLLOC_DEFAULT is run, CURRENT is set the location of the + first token. By default, to implement support for ranges, extend + its range to the last symbol. */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#if YYPURE +# if YYLSP_NEEDED +# ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +# else +# define YYLEX yylex (&yylval, &yylloc) +# endif +# else /* !YYLSP_NEEDED */ +# ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, YYLEX_PARAM) +# else +# define YYLEX yylex (&yylval) +# endif +# endif /* !YYLSP_NEEDED */ +#else /* !YYPURE */ +# define YYLEX yylex () +#endif /* !YYPURE */ + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +#endif /* !YYDEBUG */ + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + +#ifdef YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif +#endif + +#line 319 "/usr/share/bison/bison.simple" + + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +# define YYPARSE_PARAM_DECL +# else +# define YYPARSE_PARAM_ARG YYPARSE_PARAM +# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +# endif +#else /* !YYPARSE_PARAM */ +# define YYPARSE_PARAM_ARG +# define YYPARSE_PARAM_DECL +#endif /* !YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +# ifdef YYPARSE_PARAM +YYPARSE_RETURN_TYPE yyparse (void *); +# else +YYPARSE_RETURN_TYPE yyparse (void); +# endif +#endif + +/* YY_DECL_VARIABLES -- depending whether we use a pure parser, + variables are global, or local to YYPARSE. */ + +#define YY_DECL_NON_LSP_VARIABLES \ +/* The lookahead symbol. */ \ +int yychar; \ + \ +/* The semantic value of the lookahead symbol. */ \ +YYSTYPE yylval; \ + \ +/* Number of parse errors so far. */ \ +int yynerrs; + +#if YYLSP_NEEDED +# define YY_DECL_VARIABLES \ +YY_DECL_NON_LSP_VARIABLES \ + \ +/* Location data for the lookahead symbol. */ \ +YYLTYPE yylloc; +#else +# define YY_DECL_VARIABLES \ +YY_DECL_NON_LSP_VARIABLES +#endif + + +/* If nonreentrant, generate the variables here. */ + +#if !YYPURE +YY_DECL_VARIABLES +#endif /* !YYPURE */ + +YYPARSE_RETURN_TYPE +yyparse (YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + /* If reentrant, generate the variables here. */ +#if YYPURE + YY_DECL_VARIABLES +#endif /* !YYPURE */ + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yychar1 = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; + register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + +#if YYLSP_NEEDED + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; +#endif + +#if YYLSP_NEEDED +# define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +# define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + YYSIZE_T yystacksize = YYINITDEPTH; + + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; +#if YYLSP_NEEDED + YYLTYPE yyloc; +#endif + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; +#if YYLSP_NEEDED + yylsp = yyls; +#endif + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. */ +# if YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); + yyls = yyls1; +# else + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); +# endif + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + goto yyoverflowlab; + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); +# if YYLSP_NEEDED + YYSTACK_RELOCATE (yyls); +# endif +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; +#if YYLSP_NEEDED + yylsp = yyls + yysize - 1; +#endif + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yychar1 = YYTRANSLATE (yychar); + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables + which are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + YYFPRINTF (stderr, "Next token is %d (%s", + yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise + meaning of a token, for further debugging info. */ +# ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +# endif + YYFPRINTF (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %d (%s), ", + yychar, yytname[yychar1])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#if YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to the semantic value of + the lookahead token. This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + +#if YYLSP_NEEDED + /* Similarly for the default location. Let the user run additional + commands if for instance locations are ranges. */ + yyloc = yylsp[1-yylen]; + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); +#endif + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables which + are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + int yyi; + + YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++) + YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); + YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + switch (yyn) { + +case 1: +#line 62 "geometry.yy" +{ + linenum = 1; + ; + break;} +case 2: +#line 69 "geometry.yy" +{ + int i; + extern ARRAY<char*> parsestrings; + for (i = 0; i < parsestrings.Size(); i++) + delete [] parsestrings[i]; + parsestrings.SetSize(0); + ; + break;} +case 5: +#line 86 "geometry.yy" +{ parsegeom->SetSolid(yyvsp[-2].chptr, new Solid (Solid::ROOT, yyvsp[0].solidtype)); + ; + break;} +case 6: +#line 89 "geometry.yy" +{ + parsegeom->SetFlags(yyvsp[-4].chptr, parseflags); + ; + break;} +case 8: +#line 96 "geometry.yy" +{ yyval.solidtype = (Solid*)parsegeom->GetSolid(yyvsp[0].chptr); ; + break;} +case 9: +#line 97 "geometry.yy" +{ yyval.solidtype = new Solid (Solid::UNION, yyvsp[-2].solidtype, yyvsp[0].solidtype); ; + break;} +case 10: +#line 98 "geometry.yy" +{ yyval.solidtype = new Solid (Solid::SECTION, yyvsp[-2].solidtype, yyvsp[0].solidtype); ; + break;} +case 11: +#line 99 "geometry.yy" +{ yyval.solidtype = new Solid (Solid::SUB, yyvsp[0].solidtype); ; + break;} +case 12: +#line 100 "geometry.yy" +{ yyval.solidtype = yyvsp[-1].solidtype; ; + break;} +case 13: +#line 106 "geometry.yy" +{ + OneSurfacePrimitive * surf = new Sphere (Point<3> (yyvsp[-7].val, yyvsp[-5].val, yyvsp[-3].val), yyvsp[-1].val); + parsegeom -> AddSurface (surf); + surf->SetSurfaceId (0, parsegeom->GetNSurf()-1); + yyval.solidtype = new Solid (surf); + ; + break;} +case 14: +#line 116 "geometry.yy" +{ + OneSurfacePrimitive * surf = new Cylinder (Point<3> (yyvsp[-13].val, yyvsp[-11].val, yyvsp[-9].val), + Point<3> (yyvsp[-7].val, yyvsp[-5].val, yyvsp[-3].val), yyvsp[-1].val); + parsegeom->AddSurface (surf); + surf->SetSurfaceId (0, parsegeom->GetNSurf()-1); + yyval.solidtype = new Solid (surf); + ; + break;} +case 15: +#line 128 "geometry.yy" +{ + OneSurfacePrimitive * surf = new Cone (Point<3> (yyvsp[-15].val, yyvsp[-13].val, yyvsp[-11].val), + Point<3> (yyvsp[-7].val, yyvsp[-5].val, yyvsp[-3].val), yyvsp[-9].val, yyvsp[-1].val); + parsegeom->AddSurface (surf); + surf->SetSurfaceId (0, parsegeom->GetNSurf()-1); + yyval.solidtype = new Solid (surf); + ; + break;} +case 16: +#line 137 "geometry.yy" +{ + OneSurfacePrimitive * surf = new Plane ( Point<3> (yyvsp[-11].val, yyvsp[-9].val, yyvsp[-7].val), + Vec<3> (yyvsp[-5].val, yyvsp[-3].val, yyvsp[-1].val) ); + parsegeom->AddSurface (surf); + surf->SetSurfaceId (0, parsegeom->GetNSurf()-1); + yyval.solidtype = new Solid (surf); + ; + break;} +case 17: +#line 146 "geometry.yy" +{ + Primitive * nprim = new OrthoBrick (Point<3> (yyvsp[-11].val, yyvsp[-9].val, yyvsp[-7].val), + Point<3> (yyvsp[-5].val, yyvsp[-3].val, yyvsp[-1].val)); + for (int j = 0; j < nprim->GetNSurfaces(); j++) + { + parsegeom->AddSurface (&nprim->GetSurface(j)); + nprim->SetSurfaceId (j, parsegeom->GetNSurf()-1); + yyval.solidtype = new Solid (nprim); + } + ; + break;} +case 18: +#line 159 "geometry.yy" +{ + polyhedron = new Polyhedra (); + ; + break;} +case 19: +#line 164 "geometry.yy" +{ + int j; + for (j = 0; j < polyhedron->GetNSurfaces(); j++) + { + parsegeom->AddSurface (&polyhedron->GetSurface(j)); + polyhedron->SetSurfaceId (j, parsegeom->GetNSurf()-1); + yyval.solidtype = new Solid (polyhedron); + } + ; + break;} +case 20: +#line 198 "geometry.yy" +{ + Solid * nsol = yyvsp[-1].solidtype -> Copy(*parsegeom); + Vec<3> v(yyvsp[-7].val, yyvsp[-5].val, yyvsp[-3].val); + Transformation<3> trans(v); + nsol -> Transform (trans); + yyval.solidtype = nsol; + ; + break;} +case 21: +#line 207 "geometry.yy" +{ + int i; + Solid * hsol = yyvsp[-1].solidtype; + for (i = 1; i <= yyvsp[-3].val; i++) + { + Solid * nsol = yyvsp[-1].solidtype -> Copy(*parsegeom); + Vec<3> v(yyvsp[-9].val, yyvsp[-7].val, yyvsp[-5].val); + v *= i; + Transformation<3> trans(v); + nsol -> Transform (trans); + hsol = new Solid (Solid::UNION, hsol, nsol); + } + yyval.solidtype = hsol; + ; + break;} +case 22: +#line 223 "geometry.yy" +{ + Solid * nsol = yyvsp[-1].solidtype -> Copy(*parsegeom); + Point<3> c(yyvsp[-13].val, yyvsp[-11].val, yyvsp[-9].val); + Transformation<3> rot(c, yyvsp[-7].val, yyvsp[-5].val, yyvsp[-3].val); + nsol -> Transform (rot); + yyval.solidtype = nsol; + ; + break;} +case 23: +#line 234 "geometry.yy" +{ + int i; + Solid * hsol = yyvsp[-1].solidtype; + + Point<3> c(yyvsp[-15].val, yyvsp[-13].val, yyvsp[-11].val); + Transformation<3> trans(c, yyvsp[-9].val, yyvsp[-7].val, yyvsp[-5].val); + Transformation<3> multi(Vec<3>(0,0,0)); + Transformation<3> ht; + + for (i = 1; i <= yyvsp[-3].val; i++) + { + Solid * nsol = yyvsp[-1].solidtype -> Copy(*parsegeom); + nsol -> Transform (multi); + hsol = new Solid (Solid::UNION, hsol, nsol); + + ht=multi; + multi.Combine (trans, ht); + } + yyval.solidtype = hsol; + ; + break;} +case 28: +#line 295 "geometry.yy" +{ + polyhedron->AddPoint (Point<3> (yyvsp[-4].val, yyvsp[-2].val, yyvsp[0].val)); + cout << " " << yyvsp[-4].val << " " << yyvsp[-2].val << " " << yyvsp[0].val << endl; + ; + break;} +case 29: +#line 302 "geometry.yy" +{ + polyhedron->AddFace (int(yyvsp[-4].val)-1, int(yyvsp[-2].val)-1, int(yyvsp[0].val)-1); + cout << yyvsp[-4].val << " " << yyvsp[-2].val << " " << yyvsp[0].val << endl; + ; + break;} +case 30: +#line 307 "geometry.yy" +{ + cout << "face, 1 = " << yyvsp[-6].val << " " << yyvsp[-4].val << " " << yyvsp[-2].val << " " << yyvsp[0].val << endl; + polyhedron->AddFace (int(yyvsp[-6].val)-1, int(yyvsp[-4].val)-1, int(yyvsp[-2].val)-1); + polyhedron->AddFace (int(yyvsp[-6].val)-1, int(yyvsp[-2].val)-1, int(yyvsp[0].val)-1); + cout << yyvsp[-6].val << yyvsp[-4].val << yyvsp[-2].val << yyvsp[0].val << endl; + ; + break;} +case 33: +#line 321 "geometry.yy" +{ +// revolution->AddPoint (Point<2> ($1, $3)); + cout << " " << yyvsp[-2].val << " " << yyvsp[0].val << endl; + ; + break;} +case 36: +#line 338 "geometry.yy" +{ + middlecurve->AddSegment (splinep1, Point<3> (yyvsp[-10].val, yyvsp[-8].val, yyvsp[-6].val), Point<3> (yyvsp[-4].val, yyvsp[-2].val, yyvsp[0].val)); + splinep1(0) = yyvsp[-4].val; splinep1(1) = yyvsp[-2].val; splinep1(2) = yyvsp[0].val; + ; + break;} +case 37: +#line 347 "geometry.yy" +{ + bspline = new BSplineCurve2d; + bspline -> AddPoint (Point<2> (yyvsp[-2].val, yyvsp[0].val)); + cout << "first point" << endl; + ; + break;} +case 39: +#line 355 "geometry.yy" +{ ; + break;} +case 40: +#line 357 "geometry.yy" +{ + bspline -> AddPoint (Point<2> (yyvsp[-2].val, yyvsp[0].val)); + cout << "Add Point: " << yyvsp[-2].val << "-" << yyvsp[0].val << endl; + ; + break;} +case 44: +#line 379 "geometry.yy" +{ cout << "singular edge:" << yyvsp[-2].val << " between " + << yyvsp[-1].chptr << " and " << yyvsp[0].chptr << endl; + parsegeom->singedges.Append + (new SingularEdge (yyvsp[-2].val, parsegeom->GetSolid(yyvsp[-1].chptr), + parsegeom->GetSolid(yyvsp[0].chptr))); + ; + break;} +case 45: +#line 387 "geometry.yy" +{ cout << "singular point:" << yyvsp[-3].val << " between " + << yyvsp[-2].chptr << ", " << yyvsp[-1].chptr << " and " << yyvsp[0].chptr << endl; + parsegeom->singpoints.Append + (new SingularPoint (yyvsp[-3].val, parsegeom->GetSolid(yyvsp[-2].chptr), + parsegeom->GetSolid(yyvsp[-1].chptr), + parsegeom->GetSolid(yyvsp[0].chptr))); + ; + break;} +case 46: +#line 396 "geometry.yy" +{ + ARRAY<int> si1, si2; + parsegeom->GetSolid(yyvsp[-2].chptr)->GetSurfaceIndices(si1); + parsegeom->GetSolid(yyvsp[-1].chptr)->GetSurfaceIndices(si2); + + parsegeom->AddIdentification ( + new CloseSurfaceIdentification ( + parsegeom->GetNIdentifications()+1, + *parsegeom, + parsegeom->GetSurface (si1[0]), + parsegeom->GetSurface (si2[0]), + parseflags)); + ; + break;} +case 47: +#line 411 "geometry.yy" +{ + ARRAY<int> si1, si2, si3; + parsegeom->GetSolid(yyvsp[-2].chptr)->GetSurfaceIndices(si1); + parsegeom->GetSolid(yyvsp[-1].chptr)->GetSurfaceIndices(si2); + parsegeom->GetSolid(yyvsp[0].chptr)->GetSurfaceIndices(si3); + + parsegeom->AddIdentification ( + new CloseEdgesIdentification ( + parsegeom->GetNIdentifications()+1, + *parsegeom, + parsegeom->GetSurface (si1.Get(1)), + parsegeom->GetSurface (si2.Get(1)), + parsegeom->GetSurface (si3.Get(1)))); + ; + break;} +case 48: +#line 427 "geometry.yy" +{ + ARRAY<int> si1, si2; + parsegeom->GetSolid(yyvsp[-1].chptr)->GetSurfaceIndices(si1); + parsegeom->GetSolid(yyvsp[0].chptr)->GetSurfaceIndices(si2); + + parsegeom->AddIdentification ( + new PeriodicIdentification ( + parsegeom->GetNIdentifications()+1, + *parsegeom, + parsegeom->GetSurface (si1.Get(1)), + parsegeom->GetSurface (si2.Get(1)))); + ; + break;} +case 49: +#line 441 "geometry.yy" +{ + int tlonr = + parsegeom->SetTopLevelObject ((Solid*)parsegeom->GetSolid(yyvsp[-1].chptr)); + TopLevelObject * tlo = parsegeom->GetTopLevelObject (tlonr); + if (parseflags.NumListFlagDefined ("col")) + { + const ARRAY<double> & col = parseflags.GetNumListFlag ("col"); + tlo->SetRGB (col[0], col[1], col[2]); + } + if (parseflags.GetDefineFlag ("transparent")) + tlo->SetTransparent (1); + ; + break;} +case 50: +#line 455 "geometry.yy" +{ + ARRAY<int> si; + parsegeom->GetSolid(yyvsp[-1].chptr)->GetSurfaceIndices(si); + int tlonr = + parsegeom->SetTopLevelObject ((Solid*)parsegeom->GetSolid(yyvsp[-2].chptr), + (Surface*)parsegeom->GetSurface(si.Get(1))); + TopLevelObject * tlo = parsegeom->GetTopLevelObject (tlonr); + if (parseflags.NumListFlagDefined ("col")) + { + const ARRAY<double> & col = parseflags.GetNumListFlag ("col"); + tlo->SetRGB (col.Get(1), col.Get(2), col.Get(3)); + } + if (parseflags.GetDefineFlag ("transparent")) + tlo->SetTransparent (1); + ; + break;} +case 51: +#line 473 "geometry.yy" +{ + parsegeom->SetBoundingBox (Box<3> (Point<3> (yyvsp[-11].val, yyvsp[-9].val, yyvsp[-7].val), + Point<3> (yyvsp[-5].val, yyvsp[-3].val, yyvsp[-1].val))); + ; + break;} +case 52: +#line 479 "geometry.yy" +{ + parsegeom->AddUserPoint (Point<3> (yyvsp[-5].val, yyvsp[-3].val, yyvsp[-1].val)); + ; + break;} +case 53: +#line 484 "geometry.yy" +{ + CSGeometry::BCModification bcm; + ARRAY<int> si; + + parsegeom->GetSolid(yyvsp[-2].chptr)->GetSurfaceIndices(si); + + bcm.tlonr = -1; + int i; + for (i = 0; i < parsegeom->GetNTopLevelObjects(); i++) + if (strcmp (parsegeom->GetTopLevelObject(i)->GetSolid()->Name(), yyvsp[-1].chptr) == 0) + { + bcm.tlonr = i; + break; + } + + bcm.bcnr = int(yyvsp[0].val); + for (i = 0; i < si.Size(); i++) + { + bcm.si = si[i]; + parsegeom->bcmodifications.Append (bcm); + } + ; + break;} +case 54: +#line 512 "geometry.yy" +{ parseflags.DeleteFlags (); ; + break;} +case 58: +#line 523 "geometry.yy" +{ parseflags.SetFlag (yyvsp[0].chptr); ; + break;} +case 59: +#line 525 "geometry.yy" +{ parseflags.SetFlag (yyvsp[-2].chptr, yyvsp[0].chptr); ; + break;} +case 60: +#line 527 "geometry.yy" +{ parseflags.SetFlag (yyvsp[-2].chptr, yyvsp[0].val); ; + break;} +case 61: +#line 529 "geometry.yy" +{ parseflags.SetFlag (yyvsp[-2].chptr, doublearray); ; + break;} +case 62: +#line 531 "geometry.yy" +{ parseflags.SetFlag (yyvsp[-2].chptr, stringarray); ; + break;} +case 63: +#line 536 "geometry.yy" +{ doublearray.SetSize (0); ; + break;} +case 65: +#line 541 "geometry.yy" +{ doublearray.Append (yyvsp[0].val); ; + break;} +case 66: +#line 542 "geometry.yy" +{ doublearray.Append (yyvsp[0].val); ; + break;} +case 67: +#line 547 "geometry.yy" +{ + int i; + for (i = 0; i < stringarray.Size(); i++) + delete stringarray[i]; + stringarray.SetSize (0); + ; + break;} +case 69: +#line 558 "geometry.yy" +{ + stringarray.Append (new char[strlen(yyvsp[0].chptr)+1]); + strcpy (stringarray.Last(), yyvsp[0].chptr); + ; + break;} +case 70: +#line 564 "geometry.yy" +{ + stringarray.Append (new char[strlen(yyvsp[0].chptr)+1]); + strcpy (stringarray.Last(), yyvsp[0].chptr); + ; + break;} +case 71: +#line 575 "geometry.yy" +{ yyval.chptr = yyvsp[0].chptr; ; + break;} +case 72: +#line 576 "geometry.yy" +{ yyval.chptr = yyvsp[0].chptr; ; + break;} +} + +#line 709 "/usr/share/bison/bison.simple" + + + yyvsp -= yylen; + yyssp -= yylen; +#if YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; +#if YYLSP_NEEDED + *++yylsp = yyloc; +#endif + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + char *yymsg; + int yyx, yycount; + + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("parse error, unexpected ") + 1; + yysize += yystrlen (yytname[YYTRANSLATE (yychar)]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "parse error, unexpected "); + yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]); + + if (yycount < 5) + { + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx) + { + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("parse error; also virtual memory exhausted"); + } + else +#endif /* defined (YYERROR_VERBOSE) */ + yyerror ("parse error"); + } + goto yyerrlab1; + + +/*--------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action | +`--------------------------------------------------*/ +yyerrlab1: + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + YYDPRINTF ((stderr, "Discarding token %d (%s).\n", + yychar, yytname[yychar1])); + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + + +/*-------------------------------------------------------------------. +| yyerrdefault -- current state does not do anything special for the | +| error token. | +`-------------------------------------------------------------------*/ +yyerrdefault: +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + + /* If its default is to accept any token, ok. Otherwise pop it. */ + yyn = yydefact[yystate]; + if (yyn) + goto yydefault; +#endif + + +/*---------------------------------------------------------------. +| yyerrpop -- pop the current state because it cannot handle the | +| error token | +`---------------------------------------------------------------*/ +yyerrpop: + if (yyssp == yyss) + YYABORT; + yyvsp--; + yystate = *--yyssp; +#if YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "Error: state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + +/*--------------. +| yyerrhandle. | +`--------------*/ +yyerrhandle: + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; +#if YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +/*---------------------------------------------. +| yyoverflowab -- parser overflow comes here. | +`---------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} +#line 577 "geometry.yy" + + + +int yyerror (char * s) +{ + cerr << s << " in line " << linenum << endl; + return 0; +} + diff --git a/Netgen/libsrc/csg/geoml.hpp b/Netgen/libsrc/csg/geoml.hpp new file mode 100644 index 0000000000..e7974ad206 --- /dev/null +++ b/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/Netgen/libsrc/csg/identify.cpp b/Netgen/libsrc/csg/identify.cpp new file mode 100644 index 0000000000..337bc26a4a --- /dev/null +++ b/Netgen/libsrc/csg/identify.cpp @@ -0,0 +1,1483 @@ +#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 +{ + 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 +{ + 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; + s1->GetNormalVector (hsp1.p, n1); + n1 /= n1.Length(); + if ( fabs(n1 * hsp1.v) > 1e-3) + continue; + + + if (!s2->PointOnSurface(hsp2.p)) + continue; + + Vec<3> n2; + s2->GetNormalVector (hsp2.p, n2); + 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; +} + +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 * sold, *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 i; + int newpi = 0; + for (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); + + /* + (*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; + */ + } + } + } +} + + +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.p1 << "-" << seg1.p2 << ", seg2 = " << seg2.p1 << "-" << seg2.p2; + + if (side == 1) + { + if (mesh.GetIdentifications().Get (seg1.p1, seg2.p1) && + mesh.GetIdentifications().Get (seg1.p2, seg2.p2)) + { + foundother = 1; + break; + } + + if (mesh.GetIdentifications().Get (seg1.p1, seg2.p2) && + mesh.GetIdentifications().Get (seg1.p2, seg2.p1)) + { + foundother = 1; + break; + } + } + else + { + if (mesh.GetIdentifications().Get (seg2.p1, seg1.p1) && + mesh.GetIdentifications().Get (seg2.p2, seg1.p2)) + { + foundother = 1; + break; + } + + if (mesh.GetIdentifications().Get (seg2.p1, seg1.p2) && + mesh.GetIdentifications().Get (seg2.p2, seg1.p1)) + { + 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 i1, i2; + int found = 0; + int i, j, k; + int fother; + + + int facei = segs.Get(1).si; + int surfnr = mesh.GetFaceDescriptor(facei).SurfNr(); + + + if (geom.GetSurface(surfnr) == s1 || + geom.GetSurface(surfnr) == s2) + { + // (*testout) << "surfs found !" << endl; + + for (i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & sel = mesh.SurfaceElement(i); + INDEX_2 fpair (facei, sel.GetIndex()); + fpair.Sort(); + if (identfaces.Used (fpair)) + { + found = 1; + fother = sel.GetIndex(); + + // copy element + Element2d newel(3); + newel.SetIndex (facei); + for (k = 1; k <= 3; 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; + geom.GetSurface (surfnr)->GetNormalVector (mesh.Point(newel.PNum(1)), nsurf); + if (nsurf * nt < 0) + Swap (newel.PNum(2), newel.PNum(3)); + + mesh.AddSurfaceElement (newel); + } + } + } + + if (found) + { + (*mycout) << " 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 Flags & flags) + : Identification(anr, ageom) +{ + s1 = as1; + s2 = as2; + 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"); + // eps_n = 1e-3; + eps_n = 1e-6; +} + +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 +{ + int i; + double val; + + for (i = 1; i <= 1; i++) + { + if (!s1->PointOnSurface (sp1.p)) + continue; + + Vec<3> n1; + s1->GetNormalVector (sp1.p, n1); + n1.Normalize(); + if ( fabs(n1 * sp1.v) > eps_n) + continue; + + if (!s2->PointOnSurface(sp2.p)) + continue; + + Vec<3> n2; + s2->GetNormalVector (sp2.p, n2); + n2.Normalize(); + if ( fabs(n2 * sp2.v) > eps_n) + continue; + + // must have joint surface + bool joint = 0; + for (int j = 0; j < geom.GetNSurf(); j++) + { + if (geom.GetSurface(j) -> PointOnSurface(sp1.p) && + geom.GetSurface(j) -> PointOnSurface(sp2.p) ) + { + Vec<3> hn1, hn2; + geom.GetSurface(j)->GetNormalVector (sp1.p, hn1); + geom.GetSurface(j)->GetNormalVector (sp2.p, hn2); + + if (hn1 * hn2 > 0) + { + joint = 1; + break; + } + } + } + if (!joint) continue; + + Vec<3> v = sp2.p - sp1.p; + double vl = v.Length(); + double cl = fabs (v*n1); + + /* + val = 1 - cl*cl/(vl*vl); + val += (sp1.v - sp2.v).Length(); + + if (val < 1e-3) + { + return 1; + } + */ + if (cl > (1-eps_n*eps_n) * vl && (sp1.v - sp2.v).Length() < 0.1) + return 1; + } + + return 0; +} + +int CloseSurfaceIdentification :: +Identifyable (const Point<3> & p1, const Point<3> & p2) const +{ + return (s1->PointOnSurface (p1) && + s2->PointOnSurface (p2)); +} + + + + +int CloseSurfaceIdentification :: +IdentifyableCandidate (const SpecialPoint & sp1) const +{ + if (s1->PointOnSurface (sp1.p)) + { + Vec<3> n1; + s1->GetNormalVector (sp1.p, n1); + n1.Normalize(); + if ( fabs(n1 * sp1.v) > eps_n) + return 0; + return 1; + } + + if (s2->PointOnSurface (sp1.p)) + { + Vec<3> n1; + s2->GetNormalVector (sp1.p, n1); + 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 +{ + int i; + double val; + + SpecialPoint hsp1 = sp1; + SpecialPoint hsp2 = sp2; + + if ( (s1->PointOnSurface (hsp1.p) && s2->PointOnSurface (hsp2.p)) || + (s1->PointOnSurface (hsp2.p) && s2->PointOnSurface (hsp1.p)) ) + { + return 1; + } + return 0; +} + + + +int CloseSurfaceIdentification :: +GetIdentifiedPoint (class Mesh & mesh, int pi) +{ + const Surface * sold, *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->Print (*testout); + (*testout) << endl; + (*testout) << "surf2: "; + s2->Print (*testout); + (*testout) << endl; + + cerr << "GetIdenfifiedPoint: Not possible" << endl; + exit (1); + } + } + + // project to other surface + Point<3> hp = p; + snew->Project (hp); + + int i; + int newpi = 0; + for (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); + else + mesh.GetIdentifications().Add (newpi, pi, nr); + + /* + (*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 i, j; + int i1, i2; + + int np = mesh.GetNP(); + BitArray ons2(np); + ons2.Clear(); + for (i2 = 1; i2 <= np; i2++) + if (s2->PointOnSurface (mesh.Point(i2))) + ons2.Set (i2); + + for (i1 = 1; i1 <= np; i1++) + { + const Point<3> p1 = mesh.Point(i1); + if (s1->PointOnSurface (p1)) + { + int candi2 = 0; + double mindist = 1e10; + + Vec<3> n1; + s1->GetNormalVector (p1, n1); + n1.Normalize(); + + for (i2 = 1; i2 <= np; i2++) + { + if (i2 == i1) + continue; + + const Point<3> p2 = mesh.Point(i2); + + if (!ons2.Test(i2)) + continue; + /* + if (!s2->PointOnSurface (p2)) + continue; + */ + Vec<3> n = p2 - p1; + n.Normalize(); + + + 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, p1 = " + << mesh[PointIndex(i1)] << ", p2 = " + << mesh[PointIndex(candi2)] << endl; + + mesh.GetIdentifications().Add (i1, candi2, nr); + } + } + } +} + + + +void CloseSurfaceIdentification :: IdentifyFaces (class Mesh & mesh) +{ + int i, j, k, l; + int fi1, fi2, side; + + int s1rep, s2rep; + for (i = 0; i < geom.GetNSurf(); i++) + { + if (geom.GetSurface (i) == s1) + s1rep = geom.GetSurfaceClassRepresentant(i); + if (geom.GetSurface (i) == s2) + s2rep = geom.GetSurfaceClassRepresentant(i); + } + + 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 (s1rep != surfi || s2rep != 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.p1 << "-" << seg1.p2 << ", seg2 = " << seg2.p1 << "-" << seg2.p2; + + if (side == 1) + { + if (mesh.GetIdentifications().Get (seg1.p1, seg2.p1) && + mesh.GetIdentifications().Get (seg1.p2, seg2.p2)) + { + foundother = 1; + break; + } + + if (mesh.GetIdentifications().Get (seg1.p1, seg2.p2) && + mesh.GetIdentifications().Get (seg1.p2, seg2.p1)) + { + foundother = 1; + break; + } + } + else + { + if (mesh.GetIdentifications().Get (seg2.p1, seg1.p1) && + mesh.GetIdentifications().Get (seg2.p2, seg1.p2)) + { + foundother = 1; + break; + } + + if (mesh.GetIdentifications().Get (seg2.p1, seg1.p2) && + mesh.GetIdentifications().Get (seg2.p2, seg1.p1)) + { + 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 CloseSurfaceIdentification :: +BuildSurfaceElements (ARRAY<Segment> & segs, + Mesh & mesh, const Surface * surf) +{ + int i1, i2; + int found = 0, cntquads = 0; + int i, j, k; + + // insert quad layer: + for (i1 = 1; i1 <= segs.Size(); i1++) + for (i2 = 1; i2 < i1; i2++) + { + const Segment & s1 = segs.Get(i1); + const Segment & s2 = segs.Get(i2); + if ( (mesh.GetIdentifications().Get (s1.p1, s2.p2) == nr && + mesh.GetIdentifications().Get (s1.p2, s2.p1) == nr) || + (mesh.GetIdentifications().Get (s2.p1, s1.p2) == nr && + mesh.GetIdentifications().Get (s2.p2, s1.p1) == nr) + ) + { + Element2d el(4); + el.PNum(1) = s1.p1; + el.PNum(2) = s1.p2; + el.PNum(3) = s2.p1; + el.PNum(4) = s2.p2; + + Vec<3> n = Cross (Point<3> (mesh.Point(el.PNum(2)))- + Point<3> (mesh.Point(el.PNum(1))), + Point<3> (mesh.Point(el.PNum(4)))- + Point<3> (mesh.Point(el.PNum(1)))); + + Vec<3> ns; + surf->GetNormalVector (mesh.Point(el.PNum(1)), ns); + // (*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)); + } + + 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; + cntquads++; + } + } + + if (found) + { + (*mycout) << " insert quad layer of " << cntquads + << " elements at face " << segs.Get(1).si << endl; + segs.SetSize(0); + } + else + { + BuildSurfaceElements2 (segs, mesh, surf); + } + + /* + int fother; + int facei = segs.Get(1).si; + int surfnr = mesh.GetFaceDescriptor(facei).SurfNr(); + + int foundid = 0; + for (i = 1; i <= identfaces.GetNBags(); i++) + for (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) << "facei = " << facei << ", surfnr = " << surfnr << endl; + + if (foundid) + { + // (*testout) << "surfaces found" << endl; + // copy surface + for (i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & sel = mesh.SurfaceElement(i); + INDEX_2 fpair (facei, sel.GetIndex()); + fpair.Sort(); + if (identfaces.Used (fpair)) + { + found = 1; + fother = sel.GetIndex(); + + // copy element + Element2d newel(3); + newel.SetIndex (facei); + for (k = 1; k <= 3; k++) + { + newel.PNum(k) = + GetIdentifiedPoint (mesh, sel.PNum(k)); + // cout << "id-point = " << sel.PNum(k) << ", np = " << newel.PNum(k) << endl; + } + + Vec<3> nt = Cross (Vec<3> (mesh.Point (newel.PNum(1)), mesh.Point (newel.PNum(2))), + Vec<3> (mesh.Point (newel.PNum(1)), mesh.Point (newel.PNum(3)))); + Vec<3> nsurf; + geom.GetSurface (surfnr)->GetNormalVector (mesh.Point(newel.PNum(1)), nsurf); + if (nsurf * nt < 0) + Swap (newel.PNum(2), newel.PNum(3)); + + mesh.AddSurfaceElement (newel); + } + } + } + + if (found) + (*mycout) << " copy face " << facei << " from face " << fother; + } + + if (found) + segs.SetSize(0); + */ +} + + + + + + +void CloseSurfaceIdentification :: +BuildSurfaceElements2 (ARRAY<Segment> & segs, + Mesh & mesh, const Surface * surf) +{ + int i1, i2; + int found = 0, cntquads = 0; + int i, j, k; + + int fother; + int facei = segs.Get(1).si; + int surfnr = mesh.GetFaceDescriptor(facei).SurfNr(); + + int foundid = 0; + for (i = 1; i <= identfaces.GetNBags(); i++) + for (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) << "facei = " << facei << ", surfnr = " << surfnr << endl; + + /* + if (geom.GetSurface(surfnr) == s1 || + geom.GetSurface(surfnr) == s2) + */ + if (foundid) + { + // (*testout) << "surfaces found" << endl; + // copy surface + for (i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & sel = mesh.SurfaceElement(i); + INDEX_2 fpair (facei, sel.GetIndex()); + fpair.Sort(); + if (identfaces.Used (fpair)) + { + found = 1; + fother = sel.GetIndex(); + + // copy element + Element2d newel(3); + newel.SetIndex (facei); + for (k = 1; k <= 3; k++) + { + newel.PNum(k) = + GetIdentifiedPoint (mesh, sel.PNum(k)); + // cout << "id-point = " << sel.PNum(k) << ", np = " << newel.PNum(k) << endl; + } + + 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; + geom.GetSurface (surfnr)->GetNormalVector (mesh.Point(newel.PNum(1)), nsurf); + if (nsurf * nt < 0) + Swap (newel.PNum(2), newel.PNum(3)); + + mesh.AddSurfaceElement (newel); + } + } + } + + if (found) + { + (*mycout) << " 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 +{ + 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; + s1->GetNormalVector (hsp1.p, n1); + n1 /= n1.Length(); + if ( fabs(n1 * hsp1.v) > 1e-3) + continue; + + + if (!s2->PointOnSurface(hsp2.p)) + continue; + + Vec<3> n2; + s2->GetNormalVector (hsp2.p, n2); + 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 i, j; + int i1, i2; + + int np = mesh.GetNP(); + for (i1 = 1; i1 <= np; i1++) + for (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(); + + s1->GetNormalVector (p1, n1); + facet->GetNormalVector (p1, nf); + 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); + } + } +} + +void CloseEdgesIdentification :: +BuildSurfaceElements (ARRAY<Segment> & segs, + Mesh & mesh, const Surface * surf) +{ + int i1, i2; + int found = 0; + int i, j, k; + + if (surf != facet) + return; + + for (i1 = 1; i1 <= segs.Size(); i1++) + for (i2 = 1; i2 < i1; i2++) + { + const Segment & s1 = segs.Get(i1); + const Segment & s2 = segs.Get(i2); + if (mesh.GetIdentifications().Get (s1.p1, s2.p2) && + mesh.GetIdentifications().Get (s1.p2, s2.p1)) + { + Element2d el(4); + el.PNum(1) = s1.p1; + el.PNum(2) = s1.p2; + el.PNum(3) = s2.p2; + el.PNum(4) = s2.p1; + + 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; + surf->GetNormalVector (mesh.Point(el.PNum(1)), ns); + (*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/Netgen/libsrc/csg/identify.hpp b/Netgen/libsrc/csg/identify.hpp new file mode 100644 index 0000000000..b358a424c4 --- /dev/null +++ b/Netgen/libsrc/csg/identify.hpp @@ -0,0 +1,173 @@ + +#ifndef FILE_IDENTIFY +#define FILE_IDENTIFY + +/**************************************************************************/ +/* File: identify.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 1. Aug. 99 */ +/**************************************************************************/ + +/** + 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: + Identification (int anr, const CSGeometry & ageom); + virtual ~Identification (); + virtual void Print (ostream & ost) const = 0; + 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; + /// + 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; + 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 CloseSurfaceIdentification : public Identification +{ + const Surface * s1; + const Surface * s2; + /// 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; +public: + CloseSurfaceIdentification (int anr, + const CSGeometry & ageom, + const Surface * as1, + const Surface * as2, + 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; + 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; } +}; + + +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; + + + virtual void IdentifyPoints (class Mesh & mesh); + virtual void BuildSurfaceElements (ARRAY<class Segment> & segs, + class Mesh & mesh, + const Surface * surf); +}; + +#endif diff --git a/Netgen/libsrc/csg/lex.yy.cpp b/Netgen/libsrc/csg/lex.yy.cpp new file mode 100644 index 0000000000..31c180c05d --- /dev/null +++ b/Netgen/libsrc/csg/lex.yy.cpp @@ -0,0 +1,1834 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /cvsroot/gmsh/Netgen/libsrc/csg/lex.yy.cpp,v 1.1 2004-06-26 17:58:14 geuzaine Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> +#include <iostream.h> +#include <unistd.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + istream* yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + + +#define FLEX_DEBUG +typedef unsigned char YY_CHAR; +#define yytext_ptr yytext +#define YY_INTERACTIVE + +#define FLEX_DEBUG + +#include <FlexLexer.h> + + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 37 +#define YY_END_OF_BUFFER 38 +static yyconst short int yy_accept[222] = + { 0, + 0, 0, 0, 0, 0, 0, 38, 33, 32, 34, + 33, 33, 33, 30, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 37, 0, + 36, 0, 0, 30, 30, 30, 0, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 5, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 0, 35, 0, 0, 30, 31, 4, 31, + 31, 31, 31, 31, 31, 31, 31, 6, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 3, 31, + 31, 0, 30, 31, 31, 31, 13, 31, 22, 31, + + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 16, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 14, 15, 23, 31, 31, 31, + 31, 2, 31, 31, 31, 31, 31, 31, 31, 31, + 17, 31, 31, 31, 31, 31, 31, 31, 9, 31, + 11, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 12, 24, 31, 31, 31, 27, 31, 31, + 21, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 7, 31, 31, 31, 26, 31, 31, 31, + + 18, 19, 20, 1, 31, 29, 31, 10, 31, 31, + 31, 31, 31, 25, 31, 31, 8, 31, 31, 28, + 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 4, 1, 1, 1, 1, 1, + 1, 1, 5, 1, 5, 6, 1, 7, 7, 7, + 8, 7, 7, 7, 7, 7, 7, 1, 1, 1, + 1, 1, 1, 1, 9, 9, 9, 9, 10, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 1, 1, 1, 1, 1, 1, 11, 12, 13, 14, + + 15, 16, 17, 18, 19, 9, 20, 21, 22, 23, + 24, 25, 9, 26, 27, 28, 29, 30, 9, 31, + 32, 9, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[33] = + { 0, + 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2 + } ; + +static yyconst short int yy_base[226] = + { 0, + 0, 0, 0, 0, 0, 0, 77, 706, 706, 706, + 30, 29, 31, 34, 38, 40, 43, 61, 45, 47, + 50, 58, 64, 66, 87, 76, 105, 124, 706, 67, + 706, 57, 68, 0, 71, 89, 98, 82, 102, 108, + 112, 110, 114, 120, 126, 129, 133, 144, 141, 147, + 150, 153, 156, 161, 158, 163, 166, 169, 176, 178, + 185, 191, 53, 706, 199, 193, 201, 203, 205, 207, + 209, 212, 214, 216, 221, 218, 230, 232, 235, 237, + 240, 242, 244, 247, 253, 260, 262, 265, 267, 271, + 275, 277, 279, 281, 284, 288, 292, 294, 297, 299, + + 301, 303, 306, 308, 311, 313, 316, 318, 330, 332, + 334, 338, 340, 342, 346, 348, 351, 357, 368, 360, + 370, 372, 378, 380, 384, 388, 394, 396, 398, 400, + 402, 405, 409, 411, 414, 421, 423, 426, 428, 430, + 434, 436, 441, 443, 446, 448, 452, 454, 456, 463, + 468, 470, 472, 476, 478, 480, 485, 491, 482, 493, + 495, 497, 502, 505, 511, 515, 517, 519, 521, 528, + 531, 535, 540, 542, 545, 547, 550, 552, 554, 557, + 559, 561, 564, 566, 572, 575, 577, 579, 584, 586, + 590, 592, 596, 602, 610, 612, 614, 616, 619, 623, + + 628, 630, 632, 634, 638, 640, 642, 646, 648, 653, + 655, 657, 659, 661, 663, 667, 669, 672, 676, 681, + 706, 699, 701, 41, 703 + } ; + +static yyconst short int yy_def[226] = + { 0, + 221, 1, 222, 222, 222, 222, 221, 221, 221, 221, + 223, 221, 221, 221, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 221, 223, + 221, 225, 221, 14, 221, 221, 221, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 225, 221, 221, 221, 221, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 221, 221, 224, 224, 224, 224, 224, 224, 224, + + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 0, 221, 221, 221, 221 + } ; + +static yyconst short int yy_nxt[739] = + { 0, + 8, 9, 10, 11, 12, 13, 14, 14, 15, 15, + 16, 17, 18, 15, 19, 15, 20, 15, 21, 15, + 15, 22, 23, 24, 25, 26, 27, 28, 15, 15, + 15, 15, 31, 32, 33, 34, 34, 35, 35, 36, + 34, 34, 39, 37, 38, 38, 38, 38, 37, 38, + 38, 38, 38, 38, 38, 64, 38, 38, 46, 64, + 40, 47, 41, 48, 38, 38, 42, 38, 38, 31, + 38, 38, 38, 38, 35, 35, 221, 35, 35, 221, + 65, 43, 38, 38, 44, 65, 49, 50, 38, 38, + 55, 51, 45, 38, 38, 35, 35, 221, 37, 56, + + 221, 52, 66, 37, 67, 67, 221, 53, 38, 38, + 54, 38, 38, 221, 38, 38, 38, 38, 38, 38, + 38, 38, 221, 57, 68, 69, 38, 38, 58, 59, + 38, 38, 38, 38, 221, 38, 38, 71, 70, 38, + 38, 221, 72, 221, 60, 74, 73, 38, 38, 61, + 38, 38, 62, 38, 38, 75, 38, 38, 76, 38, + 38, 77, 38, 38, 38, 38, 81, 38, 38, 38, + 38, 221, 38, 38, 78, 38, 38, 79, 80, 82, + 221, 83, 38, 38, 38, 38, 221, 84, 86, 87, + 85, 38, 38, 88, 221, 90, 221, 38, 38, 67, + + 67, 89, 91, 92, 221, 93, 93, 67, 67, 38, + 38, 38, 38, 38, 38, 38, 38, 94, 38, 38, + 38, 38, 38, 38, 38, 38, 97, 38, 38, 95, + 99, 221, 98, 100, 221, 96, 38, 38, 38, 38, + 101, 38, 38, 38, 38, 221, 38, 38, 38, 38, + 38, 38, 103, 38, 38, 104, 221, 102, 105, 38, + 38, 221, 106, 110, 107, 221, 38, 38, 38, 38, + 109, 38, 38, 38, 38, 108, 111, 38, 38, 113, + 112, 38, 38, 93, 93, 93, 93, 38, 38, 115, + 38, 38, 116, 114, 38, 38, 221, 117, 38, 38, + + 38, 38, 118, 38, 38, 38, 38, 38, 38, 38, + 38, 221, 38, 38, 38, 38, 119, 38, 38, 38, + 38, 122, 38, 38, 38, 38, 221, 126, 121, 123, + 120, 124, 221, 125, 221, 128, 38, 38, 38, 38, + 38, 38, 221, 127, 38, 38, 38, 38, 38, 38, + 129, 132, 38, 38, 38, 38, 221, 38, 38, 130, + 221, 136, 131, 38, 38, 133, 38, 38, 134, 137, + 221, 138, 221, 135, 38, 38, 38, 38, 38, 38, + 141, 140, 221, 139, 38, 38, 38, 38, 142, 145, + 38, 38, 221, 146, 38, 38, 221, 143, 221, 144, + + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 147, 38, 38, 221, 149, 38, 38, 38, 38, 221, + 38, 38, 150, 151, 153, 221, 148, 38, 38, 38, + 38, 152, 38, 38, 38, 38, 38, 38, 221, 156, + 38, 38, 38, 38, 158, 155, 154, 38, 38, 38, + 38, 159, 38, 38, 38, 38, 157, 221, 38, 38, + 38, 38, 38, 38, 160, 164, 163, 221, 161, 38, + 38, 162, 221, 166, 38, 38, 38, 38, 38, 38, + 167, 165, 38, 38, 38, 38, 38, 38, 38, 38, + 168, 38, 38, 221, 170, 221, 171, 38, 38, 38, + + 38, 38, 38, 38, 38, 176, 221, 169, 38, 38, + 172, 38, 38, 174, 178, 177, 173, 38, 38, 221, + 175, 38, 38, 38, 38, 38, 38, 38, 38, 180, + 179, 183, 221, 184, 38, 38, 221, 38, 38, 185, + 181, 38, 38, 221, 182, 186, 38, 38, 38, 38, + 187, 38, 38, 38, 38, 188, 38, 38, 38, 38, + 38, 38, 190, 38, 38, 38, 38, 38, 38, 189, + 38, 194, 38, 38, 221, 193, 221, 191, 38, 38, + 192, 38, 38, 38, 38, 38, 38, 198, 221, 195, + 38, 38, 38, 38, 221, 196, 38, 38, 38, 38, + + 221, 197, 38, 38, 221, 201, 199, 221, 38, 38, + 200, 221, 202, 221, 203, 204, 38, 38, 38, 38, + 38, 38, 38, 38, 221, 38, 38, 221, 207, 38, + 38, 221, 205, 208, 38, 38, 38, 38, 38, 38, + 38, 38, 206, 209, 38, 38, 38, 38, 38, 38, + 221, 210, 38, 38, 38, 38, 211, 221, 212, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 213, 221, 38, 38, 38, 38, 217, 38, 38, + 221, 214, 38, 38, 215, 218, 216, 38, 38, 221, + 221, 221, 221, 221, 221, 219, 221, 221, 220, 29, + + 29, 30, 30, 63, 63, 7, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221 + } ; + +static yyconst short int yy_chk[739] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 11, 11, 12, 12, 12, 13, 13, 14, + 14, 14, 224, 14, 15, 15, 16, 16, 14, 17, + 17, 19, 19, 20, 20, 63, 21, 21, 19, 32, + 16, 20, 16, 21, 22, 22, 17, 18, 18, 30, + 23, 23, 24, 24, 33, 33, 7, 35, 35, 0, + 35, 18, 26, 26, 18, 35, 22, 23, 38, 38, + 26, 24, 18, 25, 25, 36, 36, 0, 36, 26, + + 0, 25, 37, 36, 37, 37, 0, 25, 39, 39, + 25, 27, 27, 0, 40, 40, 42, 42, 41, 41, + 43, 43, 0, 27, 40, 41, 44, 44, 27, 27, + 28, 28, 45, 45, 0, 46, 46, 43, 42, 47, + 47, 0, 44, 0, 28, 46, 45, 49, 49, 28, + 48, 48, 28, 50, 50, 47, 51, 51, 48, 52, + 52, 49, 53, 53, 55, 55, 53, 54, 54, 56, + 56, 0, 57, 57, 50, 58, 58, 51, 52, 54, + 0, 54, 59, 59, 60, 60, 0, 55, 57, 58, + 56, 61, 61, 59, 0, 61, 0, 62, 62, 66, + + 66, 60, 62, 65, 0, 65, 65, 67, 67, 68, + 68, 69, 69, 70, 70, 71, 71, 68, 72, 72, + 73, 73, 74, 74, 76, 76, 72, 75, 75, 70, + 74, 0, 73, 75, 0, 71, 77, 77, 78, 78, + 76, 79, 79, 80, 80, 0, 81, 81, 82, 82, + 83, 83, 79, 84, 84, 80, 0, 77, 81, 85, + 85, 0, 81, 85, 82, 0, 86, 86, 87, 87, + 84, 88, 88, 89, 89, 83, 86, 90, 90, 88, + 87, 91, 91, 92, 92, 93, 93, 94, 94, 91, + 95, 95, 94, 90, 96, 96, 0, 95, 97, 97, + + 98, 98, 96, 99, 99, 100, 100, 101, 101, 102, + 102, 0, 103, 103, 104, 104, 98, 105, 105, 106, + 106, 102, 107, 107, 108, 108, 0, 106, 101, 103, + 100, 104, 0, 105, 0, 108, 109, 109, 110, 110, + 111, 111, 0, 107, 112, 112, 113, 113, 114, 114, + 109, 112, 115, 115, 116, 116, 0, 117, 117, 110, + 0, 117, 111, 118, 118, 113, 120, 120, 114, 117, + 0, 118, 0, 116, 119, 119, 121, 121, 122, 122, + 120, 119, 0, 118, 123, 123, 124, 124, 121, 123, + 125, 125, 0, 124, 126, 126, 0, 122, 0, 122, + + 127, 127, 128, 128, 129, 129, 130, 130, 131, 131, + 128, 132, 132, 0, 130, 133, 133, 134, 134, 0, + 135, 135, 131, 133, 135, 0, 129, 136, 136, 137, + 137, 134, 138, 138, 139, 139, 140, 140, 0, 138, + 141, 141, 142, 142, 140, 137, 136, 143, 143, 144, + 144, 142, 145, 145, 146, 146, 139, 0, 147, 147, + 148, 148, 149, 149, 143, 147, 146, 0, 144, 150, + 150, 145, 0, 150, 151, 151, 152, 152, 153, 153, + 152, 148, 154, 154, 155, 155, 156, 156, 159, 159, + 153, 157, 157, 0, 155, 0, 156, 158, 158, 160, + + 160, 161, 161, 162, 162, 161, 0, 154, 163, 163, + 157, 164, 164, 159, 163, 162, 158, 165, 165, 0, + 160, 166, 166, 167, 167, 168, 168, 169, 169, 165, + 164, 168, 0, 169, 170, 170, 0, 171, 171, 170, + 166, 172, 172, 0, 167, 171, 173, 173, 174, 174, + 172, 175, 175, 176, 176, 175, 177, 177, 178, 178, + 179, 179, 177, 180, 180, 181, 181, 182, 182, 176, + 183, 183, 184, 184, 0, 182, 0, 179, 185, 185, + 180, 186, 186, 187, 187, 188, 188, 187, 0, 184, + 189, 189, 190, 190, 0, 185, 191, 191, 192, 192, + + 0, 186, 193, 193, 0, 190, 188, 0, 194, 194, + 189, 0, 191, 0, 192, 194, 195, 195, 196, 196, + 197, 197, 198, 198, 0, 199, 199, 0, 198, 200, + 200, 0, 195, 199, 201, 201, 202, 202, 203, 203, + 204, 204, 196, 200, 205, 205, 206, 206, 207, 207, + 0, 205, 208, 208, 209, 209, 207, 0, 209, 210, + 210, 211, 211, 212, 212, 213, 213, 214, 214, 215, + 215, 210, 0, 216, 216, 217, 217, 215, 218, 218, + 0, 211, 219, 219, 212, 216, 213, 220, 220, 0, + 0, 0, 0, 0, 0, 218, 0, 0, 219, 222, + + 222, 223, 223, 225, 225, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221 + } ; + +static yyconst short int yy_rule_linenum[37] = + { 0, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 54, 55, 56, 58, 59, 60, 61, 62, 63, 65, + 66, 75, 76, 77, 78, 79 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "geometry.ll" +#define INITIAL 0 +#line 2 "geometry.ll" +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> + + + + +// extern SYMBOLTABLE<Solid*> solids; +namespace netgen { +extern CSGeometry * parsegeom; +} +using namespace netgen; + +#include "geometry.h" + + +ARRAY<char*> parsestrings; +int linenum; +#define incl 1 + +#define comment 2 + +#line 594 "lex.yy.cc" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +#define ECHO LexerOutput( yytext, yyleng ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( (result = LexerInput( (char *) buf, max_size )) < 0 ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) LexerError( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yyFlexLexer::yylex() +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 32 "geometry.ll" + +#line 723 "lex.yy.cc" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = &cin; + + if ( ! yyout ) + yyout = &cout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 222 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 706 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + if ( yy_flex_debug ) + { + if ( yy_act == 0 ) + cerr << "--scanner backing up\n"; + else if ( yy_act < 37 ) + cerr << "--accepting rule at line " << yy_rule_linenum[yy_act] << + "(\"" << yytext << "\")\n"; + else if ( yy_act == 37 ) + cerr << "--accepting default rule (\"" << yytext << "\")\n"; + else if ( yy_act == 38 ) + cerr << "--(end of buffer or a NUL)\n"; + else + cerr << "--EOF (start condition " << YY_START << ")\n"; + } + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 33 "geometry.ll" +{ return TOK_RECO; } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 34 "geometry.ll" +{ return TOK_SOLID; } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 35 "geometry.ll" +{ return TOK_TLO; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 36 "geometry.ll" +{ return TOK_AND; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 37 "geometry.ll" +{ return TOK_OR; } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 38 "geometry.ll" +{ return TOK_NOT; } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 39 "geometry.ll" +{ return TOK_TRANSLATE; } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 40 "geometry.ll" +{ return TOK_MULTITRANSLATE; } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 41 "geometry.ll" +{ return TOK_ROTATE; } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 42 "geometry.ll" +{ return TOK_MULTIROTATE; } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 43 "geometry.ll" +{ return TOK_SPHERE; } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 44 "geometry.ll" +{ return TOK_CYLINDER; } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 45 "geometry.ll" +{ return TOK_CONE; } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 46 "geometry.ll" +{ return TOK_PLAIN; } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 47 "geometry.ll" +{ return TOK_PLAIN; } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 48 "geometry.ll" +{ return TOK_TUBE; } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 49 "geometry.ll" +{ return TOK_GENCYL; } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 50 "geometry.ll" +{ return TOK_ORTHOBRICK; } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 51 "geometry.ll" +{ return TOK_POLYHEDRON; } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 52 "geometry.ll" +{ return TOK_REVOLUTION; } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 54 "geometry.ll" +{ return TOK_SINGULAR; } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 55 "geometry.ll" +{ return TOK_EDGE; } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 56 "geometry.ll" +{ return TOK_POINT; } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 58 "geometry.ll" +{ return TOK_IDENTIFY; } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 59 "geometry.ll" +{ return TOK_CLOSESURFACES; } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 60 "geometry.ll" +{ return TOK_CLOSEEDGES; } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 61 "geometry.ll" +{ return TOK_PERIODIC; } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 62 "geometry.ll" +{ return TOK_BOUNDARYCONDITION; } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 63 "geometry.ll" +{ return TOK_BOUNDINGBOX; } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 65 "geometry.ll" +{ yylval.val = atof (YYText()); return NUM; } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 66 "geometry.ll" +{ + yylval.chptr = new char [YYLeng()+1]; + parsestrings.Append (yylval.chptr); + strcpy (yylval.chptr, YYText()); + if (parsegeom->GetSolid (yylval.chptr)) + return IDENTSOLID; + else + return IDENT; + } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 75 "geometry.ll" +/* eat up ws */ + YY_BREAK +case 33: +YY_RULE_SETUP +#line 76 "geometry.ll" +{ return int(*YYText()); } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 77 "geometry.ll" +{ linenum++; } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 78 "geometry.ll" +{ linenum++; cout << (YYText()+2) ; } /* line comment */ + YY_BREAK +case 36: +YY_RULE_SETUP +#line 79 "geometry.ll" +{ linenum++; } /* line comment */ + YY_BREAK +case 37: +YY_RULE_SETUP +#line 82 "geometry.ll" +ECHO; + YY_BREAK +#line 1013 "lex.yy.cc" +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(incl): +case YY_STATE_EOF(comment): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + +yyFlexLexer::yyFlexLexer( istream* arg_yyin, ostream* arg_yyout ) + { + yyin = arg_yyin; + yyout = arg_yyout; + yy_c_buf_p = 0; + yy_init = 1; + yy_start = 0; + yy_flex_debug = 0; + yylineno = 1; // this will only get updated if %option yylineno + + yy_did_buffer_switch_on_eof = 0; + + yy_looking_for_trail_begin = 0; + yy_more_flag = 0; + yy_more_len = 0; + yy_more_offset = yy_prev_more_offset = 0; + + yy_start_stack_ptr = yy_start_stack_depth = 0; + yy_start_stack = 0; + + yy_current_buffer = 0; + +#ifdef YY_USES_REJECT + yy_state_buf = new yy_state_type[YY_BUF_SIZE + 2]; +#else + yy_state_buf = 0; +#endif + } + +yyFlexLexer::~yyFlexLexer() + { + delete yy_state_buf; + yy_delete_buffer( yy_current_buffer ); + } + +void yyFlexLexer::switch_streams( istream* new_in, ostream* new_out ) + { + if ( new_in ) + { + yy_delete_buffer( yy_current_buffer ); + yy_switch_to_buffer( yy_create_buffer( new_in, YY_BUF_SIZE ) ); + } + + if ( new_out ) + yyout = new_out; + } + +#ifdef YY_INTERACTIVE +int yyFlexLexer::LexerInput( char* buf, int /* max_size */ ) +#else +int yyFlexLexer::LexerInput( char* buf, int max_size ) +#endif + { + if ( yyin->eof() || yyin->fail() ) + return 0; + +#ifdef YY_INTERACTIVE + yyin->get( buf[0] ); + + if ( yyin->eof() ) + return 0; + + if ( yyin->bad() ) + return -1; + + return 1; + +#else + (void) yyin->read( buf, max_size ); + + if ( yyin->bad() ) + return -1; + else + return yyin->gcount(); +#endif + } + +void yyFlexLexer::LexerOutput( const char* buf, int size ) + { + (void) yyout->write( buf, size ); + } + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +int yyFlexLexer::yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +yy_state_type yyFlexLexer::yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 222 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +yy_state_type yyFlexLexer::yy_try_NUL_trans( yy_state_type yy_current_state ) + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 222 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 221); + + return yy_is_jam ? 0 : yy_current_state; + } + + +void yyFlexLexer::yyunput( int c, register char* yy_bp ) + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } + + +int yyFlexLexer::yyinput() + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +void yyFlexLexer::yyrestart( istream* input_file ) + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +void yyFlexLexer::yy_load_buffer_state() + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( istream* file, int size ) + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b ) + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#include<unistd.h> +void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, istream* file ) + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + b->yy_is_interactive = 0; + } + + +void yyFlexLexer::yy_flush_buffer( YY_BUFFER_STATE b ) + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#endif + + +#ifndef YY_NO_SCAN_STRING +#endif + + +#ifndef YY_NO_SCAN_BYTES +#endif + + +#ifndef YY_NO_PUSH_STATE +void yyFlexLexer::yy_push_state( int new_state ) + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +void yyFlexLexer::yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +int yyFlexLexer::yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + + +void yyFlexLexer::LexerError( yyconst char msg[] ) + { + cerr << msg << '\n'; + exit( YY_EXIT_FAILURE ); + } + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 82 "geometry.ll" + + +extern FlexLexer * lexer; + +int yylex () + { + return lexer -> yylex(); + } + +extern "C" int yywrap () + { + return 1; + } diff --git a/Netgen/libsrc/csg/manifold.cpp b/Netgen/libsrc/csg/manifold.cpp new file mode 100644 index 0000000000..9733389d67 --- /dev/null +++ b/Netgen/libsrc/csg/manifold.cpp @@ -0,0 +1,14 @@ +#include <csg.hpp> + +namespace netgen +{ +Manifold :: Manifold () +{ + ; +} + +Manifold :: ~Manifold () +{ + ; +} +} diff --git a/Netgen/libsrc/csg/manifold.hpp b/Netgen/libsrc/csg/manifold.hpp new file mode 100644 index 0000000000..5deb7236a7 --- /dev/null +++ b/Netgen/libsrc/csg/manifold.hpp @@ -0,0 +1,22 @@ +#ifndef FILE_MANIFOLD +#define FILE_MANIFOLD + +/**************************************************************************/ +/* File: manifold.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 7. Aug. 96 */ +/**************************************************************************/ + +/** + Basis class for manifolds in 2d and 3d +*/ +class Manifold +{ +public: + /// + Manifold (); + /// + virtual ~Manifold (); +}; + +#endif diff --git a/Netgen/libsrc/csg/meshsurf.cpp b/Netgen/libsrc/csg/meshsurf.cpp new file mode 100644 index 0000000000..178133007c --- /dev/null +++ b/Netgen/libsrc/csg/meshsurf.cpp @@ -0,0 +1,178 @@ +#include <mystdlib.h> + +#include <csg.hpp> +#include <meshing.hpp> + + + +namespace netgen +{ + /* +Meshing2Surfaces :: Meshing2Surfaces (const Surface & asurface) + : surface(asurface) +{ + ; +} + */ +Meshing2Surfaces :: Meshing2Surfaces (const Surface & asurf, + const Box<3> & abb) + : Meshing2(Box3d(abb.PMin(), abb.PMax())), surface(asurf) +{ + ; +} + + +void Meshing2Surfaces :: DefineTransformation (Point3d & p1, 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, Point3d & p) const +{ + Point<3> hp = p; + geometry.GetSurface(surfind)->Project (hp); + p = hp; +} + +void MeshOptimize2dSurfaces :: ProjectPoint2 (INDEX surfind, INDEX surfind2, + Point3d & p) const +{ + Point<3> hp = p; + ProjectToEdge ( geometry.GetSurface(surfind), + geometry.GetSurface(surfind2), hp); + p = hp; +} + + +void MeshOptimize2dSurfaces :: +GetNormalVector(INDEX surfind, const Point3d & p, Vec3d & 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) +{ + ; +} + +RefinementSurfaces :: ~RefinementSurfaces () +{ + ; +} + +void RefinementSurfaces :: +PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi, + const PointGeomInfo & gi1, + const PointGeomInfo & gi2, + Point3d & newp, PointGeomInfo & newgi) +{ + 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 Point3d & p1, const Point3d & p2, double secpoint, + int surfi1, int surfi2, + const EdgePointGeomInfo & ap1, + const EdgePointGeomInfo & ap2, + Point3d & newp, EdgePointGeomInfo & newgi) +{ + Point<3> hnewp = p1+secpoint*(p2-p1); + if (surfi1 != -1 && surfi2 != -1 && surfi1 != surfi2) + { + 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; + } + else if (surfi1 != -1) + { + geometry.GetSurface (surfi1) -> Project (hnewp); + } + + newp = hnewp; +}; + + +void RefinementSurfaces :: ProjectToSurface (Point<3> & p, int surfi) +{ + if (surfi != -1) + geometry.GetSurface (surfi) -> Project (p); +}; +} diff --git a/Netgen/libsrc/csg/meshsurf.hpp b/Netgen/libsrc/csg/meshsurf.hpp new file mode 100644 index 0000000000..023c2eef70 --- /dev/null +++ b/Netgen/libsrc/csg/meshsurf.hpp @@ -0,0 +1,85 @@ +#ifndef FILE_MESHSURF +#define FILE_MESHSURF + +/// +class Meshing2Surfaces : public Meshing2 +{ + /// + const Surface & surface; + +public: + /// + // Meshing2Surfaces (const Surface & asurf); + /// + Meshing2Surfaces (const Surface & asurf, const Box<3> & aboundingbox); + +protected: + /// + virtual void DefineTransformation (Point3d & p1, 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, Point3d & p) const; + /// + virtual void ProjectPoint2 (INDEX surfind, INDEX surfind2, Point3d & p) const; + /// + virtual void GetNormalVector(INDEX surfind, const Point3d & p, Vec3d & n) const; +}; + + + + + +class RefinementSurfaces : public Refinement +{ + const CSGeometry & geometry; + +public: + RefinementSurfaces (const CSGeometry & ageometry); + virtual ~RefinementSurfaces (); + + virtual void PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi, + const PointGeomInfo & gi1, + const PointGeomInfo & gi2, + Point3d & newp, PointGeomInfo & newgi); + + virtual void PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi1, int surfi2, + const EdgePointGeomInfo & ap1, + const EdgePointGeomInfo & ap2, + Point3d & newp, EdgePointGeomInfo & newgi); + + virtual void ProjectToSurface (Point<3> & p, int surfi); +}; + + + +#endif + diff --git a/Netgen/libsrc/csg/polyhedra.cpp b/Netgen/libsrc/csg/polyhedra.cpp new file mode 100644 index 0000000000..9a6855227f --- /dev/null +++ b/Netgen/libsrc/csg/polyhedra.cpp @@ -0,0 +1,288 @@ +#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) +{ + 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; + int i, j; + for (i = 0; i < 3; i++) + { + mat(0,i) = v1(i); + mat(1,i) = v2(i); + } + CalcInverse (mat, inv); + for (i = 0; i < 3; i++) + { + w1(i) = inv(i,0); + w2(i) = inv(i,1); + } +} + + +Polyhedra :: Polyhedra () +{ + surfaceactive.SetSize(0); + surfaceids.SetSize(0); +} + +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; + + 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; + + double dist2 = MinDistTP2 (p1, p2, p3, box.Center()); + if (dist2 < sqr (box.Diam()/2)) + { + // (*testout) << "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) << "Point in Sol, p = " << p << " " << flush; + Vec<3> n, v1, v2; + + // "random numbers": + n(0) = 0.123871; + n(1) = 0.15432; + n(2) = 0.43989; + + int cnt = 0; + Point<3> pmeps (p(0) - eps, p(1) - eps, p(2) - eps); + + for (int i = 0; i < faces.Size(); i++) + { + const Point<3> & fpmax = faces[i].bbox.PMax(); + if (fpmax(0) < pmeps(0) || + fpmax(1) < pmeps(1) || + fpmax(2) < pmeps(2)) continue; + + const Point<3> & p1 = points[faces[i].pnums[0]]; + + Vec<3> v0 = p - p1; + double lam3 = -(faces[i].n * v0) / (faces[i].n * n); + + if (lam3 < -eps) continue; + Vec<3> rs = v0 + lam3 * n; + + double lam1 = (faces[i].w1 * rs); + double lam2 = (faces[i].w2 * rs); + + if (lam3 < eps) + { + if (lam1 >= -eps && lam2 >= -eps && lam1+lam2 <= 1+eps) + { + return DOES_INTERSECT; + } + } + else if (lam1 >= 0 && lam2 >= 0 && lam1+lam2 <= 1) + // lam3 > 0) + { + cnt++; + } + + } + + // (*testout) << " inside = " << (cnt % 2) << endl; + return (cnt % 2) ? IS_INSIDE : IS_OUTSIDE; +} + + + +INSOLID_TYPE Polyhedra :: VecInSolid (const Point<3> & p, + const Vec<3> & v, + double eps) const +{ + Point<3> p2 = p + (1e-3/(v.Length()+1e-16)) * v; + return PointInSolid (p2, eps); +} + +void Polyhedra :: GetPrimitiveData (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) +{ + int i; + + for (i = 0; i < planes.Size(); i++) + surfaceactive[i] = 0; + + /* + for (i = 1; i <= faces.Size(); i++) + if (FaceBoxIntersection (i, box)) + surfaceactive.Elem (faces.Get(i).planenr) = 1; + */ + + for (i = 0; i < faces.Size(); i++) + // if (faces.Get(i).bbox.Intersect (box)) + 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) +{ + return points.Append (p); +} + +int Polyhedra :: AddFace (int pi1, int pi2, int pi3) +{ + int i; + + faces.Append (Face (pi1, pi2, pi3, points)); + + 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 (i = 0; i < planes.Size(); i++) + if (pl.IsIdentic (*planes[i], inverse, 1e-6)) + { + if (!inverse) + identicto = i; + } + // cout << "is identic = " << identicto << endl; + + 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; + } + + 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; +} +} diff --git a/Netgen/libsrc/csg/polyhedra.hpp b/Netgen/libsrc/csg/polyhedra.hpp new file mode 100644 index 0000000000..d422c8ca15 --- /dev/null +++ b/Netgen/libsrc/csg/polyhedra.hpp @@ -0,0 +1,72 @@ +#ifndef FILE_POLYHEDRA +#define FILE_POLYHEDRA + + +/**************************************************************************/ +/* File: polyhedra.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 19. Mar. 2000 */ +/**************************************************************************/ + +/* + + Polyhedral primitive + +*/ + +class Polyhedra : public Primitive +{ + class Face { + public: + int pnums[3]; + int planenr; + + 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); + }; + + ARRAY<Point<3> > points; + ARRAY<Face> faces; + ARRAY<Plane*> planes; + +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; + + 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 (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); + +protected: + int FaceBoxIntersection (int fnr, const BoxSphere<3> & box) const; + // void CalcData(); +}; + +#endif diff --git a/Netgen/libsrc/csg/revolution.cpp b/Netgen/libsrc/csg/revolution.cpp new file mode 100644 index 0000000000..e235012e43 --- /dev/null +++ b/Netgen/libsrc/csg/revolution.cpp @@ -0,0 +1,151 @@ +#include <mystdlib.h> + +#include <linalg.hpp> +#include <csg.hpp> + +namespace netgen +{ + +#ifdef NONE + +Revolution :: Revolution (const Point<3> & ap1, const Point<3> & ap2) +{ + p1 = ap1; + p2 = ap2; + v12 = p2 - p1; + v12.Normalize(); +} + +Revolution :: ~Revolution () +{ + ; +} + +Primitive * Revolution :: CreateDefault () +{ + return new Revolution( Point<3> (0, 0, 0), + Point<3> (1, 0, 0)); +} + +INSOLID_TYPE Revolution :: BoxInSolid (const BoxSphere<3> & box) const +{ + int i; + + Vec<3> v = box.Center() - p1; + double x = v * v12; + double y = sqrt (v.Length2() - x*x); + + Point<2> lp1, lp2; + for (i = 1; i <= polygon.GetNP(); i++) + { + polygon.GetLine (i, lp1, lp2); + + double dist2 = MinDistLP2 (lp1, lp2, Point<2>(x,y)); + if (dist2 < sqr (box.Diam())) + return DOES_INTERSECT; + }; + + return PointInSolid (box.Center(), 1e-3 * box.Diam()); +} + + +INSOLID_TYPE Revolution :: PointInSolid (const Point<3> & p, + double eps) const +{ + int i, cnt; + + Vec<3> v(p1, p); + double x = v * v12; + double y = sqrt (v.Length2() - x*x); + + if (polygon.IsOn (Point<2> (x, y))) + return DOES_INTERSECT; + if (polygon.IsIn (Point<2> (x, y))) + return IS_INSIDE; + else + return IS_OUTSIDE; +} + + + +INSOLID_TYPE Revolution :: VecInSolid (const Point<3> & p, + const Vec<3> & v, + double eps) const +{ + Point<3> p2 = p + (1e-3/(v.Length()+1e-16)) * v; + return PointInSolid (p2, eps); +} + + +void Revolution :: GetPrimitiveData (char *& classname, + ARRAY<double> & coeffs) const +{ + classname = "Revolution"; + coeffs.SetSize(0); + coeffs.Append (polygon.GetNP()); +} + +void Revolution :: SetPrimitiveData (ARRAY<double> & coeffs) +{ + ; +} + +void Revolution :: Reduce (const BoxSphere<3> & box) +{ + int i; + + for (i = 1; i <= polygon.GetNP(); i++) + surfaceactive.Elem (i) = 0; + + + Vec<3> v = box.Center() - p1; + double x = v * v12; + double y = sqrt (v.Length2() - x*x); + + Point<2> lp1, lp2; + for (i = 1; i <= polygon.GetNP(); i++) + { + polygon.GetLine (i, lp1, lp2); + + double dist2 = MinDistLP2 (lp1, lp2, Point<2>(x,y)); + if (dist2 < sqr (box.Diam()/2)) + surfaceactive.Elem(i) = 1; + }; +} + +void Revolution :: UnReduce () +{ + for (int i = 0; i < polygon.GetNP(); i++) + surfaceactive[i] = 1; +} + + +int Revolution :: AddPoint (const Point<2> & p) +{ + polygon.AddPoint (p); + return polygon.GetNP(); +} + +void Revolution :: Finish () +{ + int i; + Point<2> lp1, lp2; + Point<3> cp1, cp2; + + for (i = 1; i <= polygon.GetNP(); i++) + { + polygon.GetLine (i, lp1, lp2); + cp1 = p1 + lp1.X() * v12; + cp2 = p1 + lp2.X() * v12; + + faces.Append (new Cone (cp1, cp2, + fabs (lp1.Y()), + fabs (lp2.Y()))); + + invsurf.Append (lp1.X() < lp2.X()); + } +} + + +#endif +} diff --git a/Netgen/libsrc/csg/revolution.hpp b/Netgen/libsrc/csg/revolution.hpp new file mode 100644 index 0000000000..d57102d306 --- /dev/null +++ b/Netgen/libsrc/csg/revolution.hpp @@ -0,0 +1,65 @@ +#ifndef FILE_REVOLUTION +#define FILE_REVOLUTION + + +/**************************************************************************/ +/* File: revolution.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 12. Oct. 2000 */ +/**************************************************************************/ + +/* + + Primitive of revolution + +*/ + + +#ifdef NONE + +class Revolution : public Primitive +{ + Point<3> p1, p2; + Vec<3> v12; + Polygon2d polygon; + ARRAY<Cone*> faces; + ARRAY<int> invsurf; +public: + Revolution (const Point<3> & ap1, const Point<3> & ap2); + ~Revolution (); + 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; + + virtual int GetNSurfaces() const + { return faces.Size(); } + virtual Surface & GetSurface (int i) + { return *faces.Elem(i); } + virtual const Surface & GetSurface (int i = 1) const + { return *faces.Get(i); } + + virtual int SurfaceInverted (int i = 1) const + { return invsurf.Get(i); } + + virtual void GetPrimitiveData (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<2> & p); + void Finish (); +protected: + // int FaceBoxIntersection (int fnr, const BoxSphere<3> & box) const; + // void CalcData(); +}; + + +#endif + +#endif diff --git a/Netgen/libsrc/csg/singularref.cpp b/Netgen/libsrc/csg/singularref.cpp new file mode 100644 index 0000000000..b445d0085b --- /dev/null +++ b/Netgen/libsrc/csg/singularref.cpp @@ -0,0 +1,134 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +namespace netgen +{ + +SingularEdge :: SingularEdge (double abeta, + const Solid * asol1, + const Solid * asol2) +{ + beta = abeta; + + 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; +} + +void SingularEdge :: FindPointsOnEdge (class Mesh & mesh) +{ + (*testout) << "find points on edge" << endl; + int i, j; + points.SetSize(0); + segms.SetSize(0); + for (i = 1; i <= mesh.GetNSeg(); i++) + { + INDEX_2 i2 (mesh.LineSegment(i).p1, + mesh.LineSegment(i).p2); + + int onedge = 1; + for (j = 1; j <= 2; j++) + { + const Point<3> p = mesh.Point(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 (onedge) + { + segms.Append (i2); + cout << "sing segment << " << i2 << endl; + points.Append (mesh.Point(i2.I1())); + points.Append (mesh.Point(i2.I2())); + } + } + + + (*testout) << "Singular points:" << endl; + for (i = 1; i <= points.Size(); i++) + (*testout) << points.Get(i) << endl; + /* + for (i = 1; i <= mesh.GetNP(); i++) + { + const Point<3> p = mesh.Point(i); + if (sol1->IsIn (p) && sol2->IsIn(p) && + !sol1->IsStrictIn (p) && !sol2->IsStrictIn(p)) + { + points.Append (p); + cout << "Point " << p << " is on singular edge" << endl; + } + } + */ +} + +void SingularEdge :: SetMeshSize (class Mesh & mesh, double globalh) +{ + int i; + + double hloc = pow (globalh, 1/beta); + for (i = 1; i <= points.Size(); i++) + mesh.RestrictLocalH (points.Get(i), hloc); +} + + + + + + +SingularPoint :: SingularPoint (double abeta, + const Solid * asol1, + const Solid * asol2, + const Solid * asol3) +{ + beta = abeta; + sol1 = asol1; + sol2 = asol2; + sol3 = asol3; +} + + +void SingularPoint :: FindPoints (class Mesh & mesh) +{ + int i; + points.SetSize(0); + for (i = 1; i <= mesh.GetNP(); i++) + { + const Point<3> p = mesh.Point(i); + if (sol1->IsIn (p) && sol2->IsIn(p) && sol3->IsIn(p) && + !sol1->IsStrictIn (p) && !sol2->IsStrictIn(p) && !sol3->IsStrictIn(p)) + { + points.Append (p); + cout << "Point " << p << " is a singular point" << endl; + } + } +} + + +void SingularPoint :: SetMeshSize (class Mesh & mesh, double globalh) +{ + int i; + + double hloc = pow (globalh, 1/beta); + for (i = 1; i <= points.Size(); i++) + mesh.RestrictLocalH (points.Get(i), hloc); +} +} diff --git a/Netgen/libsrc/csg/singularref.hpp b/Netgen/libsrc/csg/singularref.hpp new file mode 100644 index 0000000000..b2d2f2d839 --- /dev/null +++ b/Netgen/libsrc/csg/singularref.hpp @@ -0,0 +1,45 @@ +#ifndef FILE_SINGULARREF +#define FILE_SINGULARREF + +/**************************************************************************/ +/* File: singularref.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 25. Sep. 99 */ +/**************************************************************************/ + +/** + Control for local refinement +*/ + + + +class SingularEdge +{ +public: + double beta; + const Solid *sol1, *sol2; + ARRAY<Point<3> > points; + ARRAY<INDEX_2> segms; +public: + SingularEdge (double abeta, const Solid * asol1, const Solid * asol2); + 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; + +public: + SingularPoint (double abeta, const Solid * asol1, const Solid * asol2, + const Solid * asol3); + void FindPoints (class Mesh & mesh); + void SetMeshSize (class Mesh & mesh, double globalh); +}; + + +#endif diff --git a/Netgen/libsrc/csg/solid.cpp b/Netgen/libsrc/csg/solid.cpp new file mode 100644 index 0000000000..5ea936c1d1 --- /dev/null +++ b/Netgen/libsrc/csg/solid.cpp @@ -0,0 +1,1285 @@ +#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; + + /* + cntnames ++; + name = new char[16]; + sprintf (name, "noname%d", cntnames); + */ + name = NULL; // name by number ? +} + +Solid :: Solid (optyp aop, Solid * as1, Solid * as2) +{ + op = aop; + s1 = as1; + s2 = as2; + prim = NULL; + name = NULL; + maxh = 1e10; +} + +Solid :: ~Solid () +{ + delete [] name; + + switch (op) + { + case UNION: + case SECTION: + { + delete s1; + delete s2; + break; + } + case SUB: + // case ROOT: + { + delete s1; + 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; + switch (op) + { + case TERM: + { + Primitive * nprim = prim->Copy(); + + for (int j = 0; j < nprim->GetNSurfaces(); j++) + { + geom.AddSurface (&nprim->GetSurface(j)); + nprim->SetSurfaceId (j, geom.GetNSurf()-1); + } + nsol = new Solid (nprim); + break; + } + case SECTION: + case UNION: + { + Solid *nsol1, *nsol2; + + nsol1 = s1 -> Copy (geom); + nsol2 = s2 -> Copy (geom); + + nsol = new Solid (op, nsol1, nsol2); + break; + } + + case SUB: + { + Solid * nsol1 = s1 -> Copy (geom); + nsol = new Solid (SUB, nsol1); + break; + } + + case ROOT: + { + nsol = s1->Copy(geom); + break; + } + } + return nsol; +} + + +void Solid :: Transform (Transformation<3> & trans) +{ + switch (op) + { + case TERM: + { + 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, + int 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; + } + } +} + + + + +int Solid :: IsIn (const Point<3> & p, double eps) const +{ + int hv1, hv2; + switch (op) + { + case TERM: + { + 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; +} + +int Solid :: IsStrictIn (const Point<3> & p, double eps) const +{ + switch (op) + { + case TERM: + { + 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; +} + +int Solid :: VectorIn (const Point<3> & p, const Vec<3> & v, + double eps) const +{ + Vec<3> hv; + switch (op) + { + case TERM: + { + 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; +} + +int Solid :: VectorStrictIn (const Point<3> & p, const Vec<3> & v, + double eps) const +{ + Vec<3> hv; + switch (op) + { + case TERM: + { + INSOLID_TYPE ist = prim->VecInSolid (p, v, eps); + return (ist == IS_INSIDE) ? 1 : 0; + } + 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; +} + + +int 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; + + return VectorIn2Rec (p, v1, v2, eps); +} + +int Solid::VectorIn2Rec (const Point<3> & p, const Vec<3> & v1, + const Vec<3> & v2, double eps) const +{ + int hv1, hv2; + switch (op) + { + case TERM: + return prim->VecInSolid2 (p, v1, v2, eps); + 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: + { + 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: + { + 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; + int i; + for (i = 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; + int i; + for (i = 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: + { + /* + 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) const +{ + int in, strin; + RecTangentialSolid (p, tansol, in, strin); +} + +void Solid :: RecTangentialSolid (const Point<3> & p, Solid *& tansol, + int & in, int & strin) const +{ + tansol = NULL; + + switch (op) + { + case TERM: + { + /* + 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, 1e-6); + + in = (ist == IS_INSIDE || ist == DOES_INTERSECT); + strin = (ist == IS_INSIDE); + + if (ist == DOES_INTERSECT) + tansol = new Solid (prim); + break; + } + case SECTION: + { + int in1, in2, strin1, strin2; + Solid * tansol1, * tansol2; + + s1 -> RecTangentialSolid (p, tansol1, in1, strin1); + s2 -> RecTangentialSolid (p, tansol2, in2, strin2); + + 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 -> RecTangentialSolid (p, tansol1, in1, strin1); + s2 -> RecTangentialSolid (p, tansol2, in2, strin2); + + 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 -> RecTangentialSolid (p, tansol1, hin, hstrin); + + if (tansol1) + tansol = new Solid (SUB, tansol1); + in = !hstrin; + strin = !hin; + break; + } + case ROOT: + { + s1 -> RecTangentialSolid (p, tansol, in, strin); + break; + } + } +} + + + + +void Solid :: TangentialSolid2 (const Point<3> & p, + const Vec<3> & t, + Solid *& tansol) const +{ + int in, strin; + RecTangentialSolid2 (p, t, tansol, in, strin); +} + +void Solid :: RecTangentialSolid2 (const Point<3> & p, const Vec<3> & t, + Solid *& tansol, + int & in, int & strin) const +{ + tansol = NULL; + + switch (op) + { + case TERM: + { + /* + 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, 1e-6); + if (ist == DOES_INTERSECT) + ist = prim->VecInSolid (p, t, 1e-6); + + in = (ist == IS_INSIDE || ist == DOES_INTERSECT); + strin = (ist == IS_INSIDE); + + if (ist == DOES_INTERSECT) + tansol = new Solid (prim); + break; + } + case SECTION: + { + int in1, in2, strin1, strin2; + Solid * tansol1, * tansol2; + + s1 -> RecTangentialSolid2 (p, t, tansol1, in1, strin1); + s2 -> RecTangentialSolid2 (p, t, tansol2, in2, strin2); + + 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, in1, strin1); + s2 -> RecTangentialSolid2 (p, t, tansol2, in2, strin2); + + 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, hin, hstrin); + + if (tansol1) + tansol = new Solid (SUB, tansol1); + in = !hstrin; + strin = !hin; + break; + } + case ROOT: + { + s1 -> RecTangentialSolid2 (p, t, tansol, in, strin); + break; + } + } +} + + + + +int Solid :: Edge (const Point<3> & p, const Vec<3> & v) const +{ + int in, strin, faces; + RecEdge (p, v, in, strin, faces); + return faces >= 2; +} + +int Solid :: OnFace (const Point<3> & p, const Vec<3> & v) const +{ + int in, strin, faces; + RecEdge (p, v, in, strin, faces); + return faces >= 1; +} + + +void Solid :: RecEdge (const Point<3> & p, const Vec<3> & v, + int & in, int & strin, int & faces) const +{ + switch (op) + { + case TERM: + { + INSOLID_TYPE ist = prim->VecInSolid (p, v, 1e-6); + 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 = 1; i <= prim->GetNSurfaces(); i++) + { + double val = prim->GetSurface(i).CalcFunctionValue(p); + prim->GetSurface(i).CalcGradient (p, grad); + if (fabs (val) < 1e-6 && 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); + s2 -> RecEdge (p, v, in2, strin2, faces2); + + 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); + s2 -> RecEdge (p, v, in2, strin2, faces2); + + 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); + in = !strin1; + strin = !in1; + break; + } + case ROOT: + { + s1 -> RecEdge (p, v, in, strin, faces); + break; + } + } +} + + +void Solid :: CalcSurfaceInverse () +{ + CalcSurfaceInverseRec (0); +} + +void Solid :: CalcSurfaceInverseRec (int inv) +{ + switch (op) + { + case TERM: + { + int priminv; + for (int i = 0; i < prim->GetNSurfaces(); i++) + { + priminv = prim->SurfaceInverted(i); + if (inv) priminv = 1 - 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 +{ + int in; + Solid * res = RecGetReducedSolid (box, in); + return res; +} + +Solid * Solid :: RecGetReducedSolid (const BoxSphere<3> & box, int & in) const +{ + Solid * redsol = NULL; + + switch (op) + { + case TERM: + { + /* really old + in = surf -> BoxInSolid (box); + if (in == 2) // maybe + redsol = new Solid (surf, id); + */ + in = int(prim -> BoxInSolid (box)); + if (in == 2) // maybe + redsol = new Solid (prim); + + // prim->GetSurface(1).Print (*testout); + + break; + } + case SECTION: + { + int in1, in2; + Solid * redsol1, * redsol2; + + redsol1 = s1 -> RecGetReducedSolid (box, in1); + redsol2 = s2 -> RecGetReducedSolid (box, in2); + + if (in1 == 0 || in2 == 0) + { + if (in1 == 2) delete redsol1; + if (in2 == 2) delete redsol2; + in = 0; + } + else + { + if (in1 == 2 || in2 == 2) in = 2; + else in = 1; + + if (in1 == 2 && in2 == 2) + redsol = new Solid (SECTION, redsol1, redsol2); + else if (in1 == 2) + redsol = redsol1; + else if (in2 == 2) + redsol = redsol2; + } + break; + } + + case UNION: + { + int in1, in2; + Solid * redsol1, * redsol2; + + redsol1 = s1 -> RecGetReducedSolid (box, in1); + redsol2 = s2 -> RecGetReducedSolid (box, in2); + + if (in1 == 1 || in2 == 1) + { + if (in1 == 2) delete redsol1; + if (in2 == 2) delete redsol2; + in = 1; + } + else + { + if (in1 == 2 || in2 == 2) in = 2; + else in = 0; + + if (in1 == 2 && in2 == 2) + redsol = new Solid (UNION, redsol1, redsol2); + else if (in1 == 2) + redsol = redsol1; + else if (in2 == 2) + redsol = redsol2; + } + break; + } + + case SUB: + { + int in1; + Solid * redsol1; + redsol1 = s1 -> RecGetReducedSolid (box, in1); + switch (in1) + { + case 0: in = 1; break; + case 1: in = 0; break; + case 2: in = 2; break; + } + if (redsol1) + redsol = new Solid (SUB, redsol1); + break; + } + + case ROOT: + { + int in1; + redsol = s1 -> RecGetReducedSolid (box, in1); + in = in1; + break; + } + } + return redsol; +} + + +int Solid :: NumPrimitives () const +{ + switch (op) + { + case TERM: + { + 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: + { + /* + int i; + for (i = 1; i <= surfind.Size(); i++) + if (surfind.Get(i) == prim->GetSurfaceId()) + return; + surfind.Append (prim->GetSurfaceId()); + break; + */ + int i, j; + for (j = 0; j < prim->GetNSurfaces(); j++) + if (prim->SurfaceActive (j)) + { + bool found = 0; + int siprim = prim->GetSurfaceId(j); + + for (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 :: GetSurfaceIndices (IndexSet & iset) const +{ + iset.Clear(); + RecGetSurfaceIndices (iset); +} + +void Solid :: RecGetSurfaceIndices (IndexSet & iset) const +{ + switch (op) + { + case TERM: + { + /* + int i; + for (i = 1; i <= surfind.Size(); i++) + if (surfind.Get(i) == prim->GetSurfaceId()) + return; + surfind.Append (prim->GetSurfaceId()); + break; + */ + int i, j; + for (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; + } + } +} + + + + + + +BlockAllocator Solid :: ball(sizeof (Solid)); + + +void * Solid :: operator new(size_t s) +{ + return ball.Alloc(); +} + +void Solid :: operator delete (void * p) +{ + ball.Free (p); +} + + + + + + +ReducePrimitiveIterator :: +ReducePrimitiveIterator (const BoxSphere<3> & abox) + : SolidIterator(), box(abox) +{ + ; +} + +ReducePrimitiveIterator :: +~ReducePrimitiveIterator () +{ + ; +} + +void +ReducePrimitiveIterator :: Do (Solid * sol) +{ + if (sol -> GetPrimitive()) + sol -> GetPrimitive() -> Reduce (box); +} + + + + +UnReducePrimitiveIterator :: +UnReducePrimitiveIterator () + : SolidIterator() +{ + ; +} + +UnReducePrimitiveIterator :: +~UnReducePrimitiveIterator () +{ + ; +} + +void +UnReducePrimitiveIterator :: Do (Solid * sol) +{ + if (sol -> GetPrimitive()) + sol -> GetPrimitive() -> UnReduce (); +} +} diff --git a/Netgen/libsrc/csg/solid.hpp b/Netgen/libsrc/csg/solid.hpp new file mode 100644 index 0000000000..b09d8fd682 --- /dev/null +++ b/Netgen/libsrc/csg/solid.hpp @@ -0,0 +1,163 @@ +#ifndef FILE_SOLID +#define FILE_SOLID + +/**************************************************************************/ +/* File: solid.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 1. Dez. 95 */ +/**************************************************************************/ + +/* + + 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, SECTION, UNION, SUB, ROOT, DUMMY } optyp; + +private: + char * name; + Primitive * prim; + Solid * s1, * s2; + + optyp op; + int visited; + double maxh; + + static int cntnames; + +public: + Solid (Primitive * aprim); + Solid (optyp aop, Solid * as1, Solid * as2 = NULL); + virtual ~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, int 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; + + Primitive * GetPrimitive () + { return (op == TERM) ? prim : NULL; } + const Primitive * GetPrimitive () const + { return (op == TERM) ? prim : NULL; } + + // geometric tests + + int IsIn (const Point<3> & p, double eps = 1e-6) const; + int IsStrictIn (const Point<3> & p, double eps = 1e-6) const; + int VectorIn (const Point<3> & p, const Vec<3> & v, double eps = 1e-6) const; + int VectorStrictIn (const Point<3> & p, const Vec<3> & v, double eps = 1e-6) const; + + int VectorIn2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, + double eps = 1e-6) const; + int VectorIn2Rec (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, + double eps = 1e-6) const; + + + /// + void TangentialSolid (const Point<3> & p, Solid *& tansol) const; + /// + void TangentialSolid2 (const Point<3> & p, const Vec<3> & t, + Solid *& tansol) const; + /// + int Edge (const Point<3> & p, const Vec<3> & v) const; + /// + int OnFace (const Point<3> & p, const Vec<3> & v) const; + /// + virtual 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); + void operator delete (void *); + +protected: + /// + + void RecBoundaries (const Point<3> & p, ARRAY<int> & bounds, + int & in, int & strin) const; + /// + void RecTangentialSolid (const Point<3> & p, Solid *& tansol, + int & in, int & strin) const; + /// + void RecTangentialSolid2 (const Point<3> & p, const Vec<3> & vec, + Solid *& tansol, int & in, int & strin) const; + /// + void RecEdge (const Point<3> & p, const Vec<3> & v, + int & in, int & strin, int & faces) const; + /// + void CalcSurfaceInverseRec (int inv); + /// + Solid * RecGetReducedSolid (const BoxSphere<3> & box, int & in) const; + /// + void RecGetSurfaceIndices (ARRAY<int> & surfind) const; + void RecGetSurfaceIndices (IndexSet & iset) const; + + friend class SolidIterator; + friend class ClearVisitedIt; + friend class RemoveDummyIterator; + friend class CSGeometry; +}; + + +class ReducePrimitiveIterator : public SolidIterator +{ + const BoxSphere<3> & box; +public: + ReducePrimitiveIterator (const BoxSphere<3> & abox); + virtual ~ReducePrimitiveIterator (); + virtual void Do (Solid * sol); +}; + + +class UnReducePrimitiveIterator : public SolidIterator +{ +public: + UnReducePrimitiveIterator (); + virtual ~UnReducePrimitiveIterator (); + virtual void Do (Solid * sol); +}; + +#endif diff --git a/Netgen/libsrc/csg/specpoin.cpp b/Netgen/libsrc/csg/specpoin.cpp new file mode 100644 index 0000000000..12fe79966a --- /dev/null +++ b/Netgen/libsrc/csg/specpoin.cpp @@ -0,0 +1,1369 @@ +#include <mystdlib.h> +#include <meshing.hpp> +#include <csg.hpp> + + +/* + + Special Point calculation uses the global Flags: + + + size .. 500 cube = [-size, size]^3 + 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 +*/ + + +namespace netgen +{ +void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp); + + + + /* +SpecialPoint :: SpecialPoint () + : p(), v(), layer(0) +{ + ; +} + */ + + +SpecialPoint :: SpecialPoint (const SpecialPoint & sp) +{ + p = sp.p; + v = sp.v; + s1 = sp.s1; + s2 = sp.s2; + layer = sp.layer; + unconditional = sp.unconditional; +} + +SpecialPoint & SpecialPoint :: operator= (const SpecialPoint & sp) +{ + p = sp.p; + v = sp.v; + s1 = sp.s1; + s2 = sp.s2; + layer = sp.layer; + unconditional = sp.unconditional; + return *this; +} + +bool SpecialPoint :: HasSurfaces (int as1, int as2) const +{ + return (s1 == as1 && s2 == as2 || s1 == as2 && s2 == as1); +} + +void SpecialPoint :: Print (ostream & str) +{ + str << "p = " << p << " v = " << v + << " s1/s2 = " << s1 << "/" << s2 + << " layer = " << layer + << endl; +} + + + + +SpecialPointCalculation :: SpecialPointCalculation () +{ + ; +} + +void SpecialPointCalculation :: +CalcSpecialPoints (const CSGeometry & ageometry, + ARRAY<MeshPoint> & apoints) +{ + int i; + + geometry = &ageometry; + points = &apoints; + + size = geometry->MaxSize(); // globflags.GetNumFlag ("maxsize", 500); + (*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()); + + for (i = 0; i < geometry->GetNTopLevelObjects(); i++) + { + (*testout) << "tlo " << i << ":" << endl; + const TopLevelObject * tlo = geometry->GetTopLevelObject(i); + tlo->GetSolid()->Print (*testout); + (*testout) << endl; + CalcSpecialPointsRec (tlo->GetSolid(), tlo->GetLayer(), + box, 1, 1, 1); + } + + PrintDot ('\n'); + + + // add user point: + int found = 0; + for (i = 0; i < geometry->GetNUserPoints(); i++) + AddPoint (geometry->GetUserPoint(i), 1); + + PrintMessage (3, apoints.Size(), " special points"); + + for (i = 0; i < boxesinlevel.Size(); i++) + (*testout) << "level " << i << " has " + << boxesinlevel[i] << " boxes" << endl; +} + + + +int debug; +void SpecialPointCalculation :: +CalcSpecialPointsRec (const Solid * sol, int layer, + const BoxSphere<3> & box, + int level, bool calccp, bool calcep) +{ + if (multithread.terminate) + return; + + int i; + BoxSphere<3> sbox; + Solid * redsol; + + int numprim; + + bool decision; + bool possiblecrossp, possibleexp; // possible cross or extremalpoint + bool surecrossp, sureexp; // sure ... + + static ARRAY<int> locsurf; // attention: array is static + + + Point<3> p; + int k1, k2, k3; + int extremdir; + double hd; + + if (!sol) return; + + + if (level >= 100) + { + cerr << "Problems in CalcSpecialPoints" << endl; + cerr << "Point: " << box.Center() << endl; + exit (1); + } + + static int cntbox = 0; + cntbox++; + if (cntbox % 10000 == 0) + PrintDot (); + + if (level <= boxesinlevel.Size()) + boxesinlevel.Elem(level)++; + else + boxesinlevel.Append (1); + + /* + numprim = sol -> NumPrimitives(); + sol -> GetSurfaceIndices (locsurf); + */ + + debug = 0; + // box.IsIn (Point<3> (4.9, 1.279, 2.8)); + + + geometry -> GetIndependentSurfaceIndices (sol, box, locsurf); + numprim = locsurf.Size(); + + if (debug) + { + (*testout) << "box = " << box.PMin() << "-" << box.PMax() + << " np = " << numprim << " : "; + for (i = 1; i <= locsurf.Size(); i++) + (*testout) << " " << locsurf.Get(i); + (*testout) << " diam = " << box.Diam(); + (*testout) << " numprim = " << numprim; + (*testout) << endl; + } + + p = box.Center(); + + /* + (*testout) << "box = " << box.PMin() << " - " << box.PMax() + << ", lev = " << level + << ", nprim = " << sol->NumPrimitives() + << ", lsurf = " << locsurf.Size() << endl; + + for (i = 1; i <= locsurf.Size(); i++) + geometry->GetSurface (locsurf.Get(i)) -> Print (*testout); + sol -> Print (*testout); + */ + + /* + for (i = 1; i <= locsurf.Size(); i++) + (*testout) << locsurf.Get(i) << " "; + (*testout) << "C = " << box.Center() << " diam = " << box.Diam() << endl; + */ + + possiblecrossp = (numprim >= 3) && calccp; + surecrossp = 0; + + if (possiblecrossp && (locsurf.Size() <= 10)) + { + decision = 1; + surecrossp = 0; + + for (k1 = 1; k1 <= locsurf.Size() - 2; k1++) + for (k2 = k1 + 1; k2 <= locsurf.Size() - 1; k2++) + for (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)), p ); + + deg = CrossPointDegenerated + (geometry->GetSurface(locsurf.Get(k1)), + geometry->GetSurface(locsurf.Get(k2)), + geometry->GetSurface(locsurf.Get(k3)), box ); + + if (!nc && !deg) decision = 0; + if (nc) surecrossp = 1; + } + + if (decision && surecrossp) + { + for (k1 = 1; k1 <= locsurf.Size() - 2; k1++) + for (k2 = k1 + 1; k2 <= locsurf.Size() - 1; k2++) + for (k3 = k2 + 1; k3 <= locsurf.Size(); k3++) + { + if (CrossPointNewtonConvergence + (geometry->GetSurface(locsurf.Get(k1)), + geometry->GetSurface(locsurf.Get(k2)), + geometry->GetSurface(locsurf.Get(k3)), p ) ) + { + 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); + + if (pp(0) > box.PMin()(0) - 1e-5 && + pp(0) < box.PMax()(0) + 1e-5 && + pp(1) > box.PMin()(1) - 1e-5 && + pp(1) < box.PMax()(1) + 1e-5 && + pp(2) > box.PMin()(2) - 1e-5 && + pp(2) < box.PMax()(2) + 1e-5 && + sol -> IsIn (pp) && !sol->IsStrictIn (pp) && + !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); + boxp.CalcDiamCenter(); + ARRAY<int> locsurf2; + + geometry -> GetIndependentSurfaceIndices (sol, boxp, locsurf2); + + /* + ReducePrimitiveIterator rpi(boxp); + UnReducePrimitiveIterator urpi; + + ((Solid*)sol) -> IterateSolid (rpi); + sol -> GetIndependentSurfaceIndices (locsurf2); + ((Solid*)sol) -> IterateSolid (urpi); + */ + bool found1 = 0, found2 = 0, found3 = 0; + for (i = 1; i <= locsurf2.Size(); i++) + { + if (locsurf2.Get(i) == locsurf.Get(k1)) + found1 = 1; + if (locsurf2.Get(i) == locsurf.Get(k2)) + found2 = 1; + if (locsurf2.Get(i) == locsurf.Get(k3)) + found3 = 1; + } + + if (found1 && found2 && found3) + if (AddPoint (pp, layer)) + { + (*testout) << "Crosspoint found: " << pp + << " diam = " << box.Diam() << endl; + (*testout) << "surfs: " + << locsurf.Get(k1) << "," + << locsurf.Get(k2) << "," + << locsurf.Get(k3) << endl; + } + } + } + } + } + + if (decision) + possiblecrossp = 0; + } + + + + + possibleexp = (numprim >= 2) && calcep; + + if (possibleexp && (locsurf.Size() <= 10)) + { + decision = 1; + sureexp = 0; + + for (k1 = 1; k1 <= locsurf.Size() - 1; k1++) + for (k2 = k1+1; k2 <= locsurf.Size(); k2++) + { + bool nc, deg; + + nc = EdgeNewtonConvergence + (geometry->GetSurface(locsurf.Get(k1)), + geometry->GetSurface(locsurf.Get(k2)), + p); + + deg = EdgeDegenerated + (geometry->GetSurface(locsurf.Get(k1)), + geometry->GetSurface(locsurf.Get(k2)), + box); + + if (!nc && !deg) decision = 0; + if (nc) sureexp = 1; + + if (debug) + { + (*testout) << "p = " << p << " s1,2 = " << locsurf.Get(k1) << ", " << locsurf.Get(k2) + << " nc = " << nc << " deg = " << deg << endl; + } + } + + if (decision && sureexp) + { + for (k1 = 1; k1 <= locsurf.Size() - 1; k1++) + for (k2 = k1+1; k2 <= locsurf.Size(); k2++) + { + if ( + EdgeNewtonConvergence + (geometry->GetSurface(locsurf.Get(k1)), + geometry->GetSurface(locsurf.Get(k2)), + p) ) + { + EdgeNewton + (geometry->GetSurface(locsurf.Get(k1)), + geometry->GetSurface(locsurf.Get(k2)), + p); + + Point<3> pp; + if (IsEdgeExtremalPoint + (geometry->GetSurface(locsurf.Get(k1)), + geometry->GetSurface(locsurf.Get(k2)), + p, pp, box.Diam()/2)) + { + (*testout) << "extremalpoint (nearly) found:" + << pp + << endl; + if (Dist (pp, box.Center()) < box.Diam()/2 && + sol -> IsIn (pp) && !sol->IsStrictIn (pp) ) + { + // AddExtremalPoint (locsurf.Get(k1), locsurf.Get(k2), p); + if (AddPoint (pp, layer)) + (*testout) << "Extremal point found: " << pp << endl; + } + } + } + } + } + if (decision) + possibleexp = 0; + } + + + + if (possiblecrossp || possibleexp) + { + for (i = 0; i < 8; i++) + { + box.GetSubBox (i, sbox); + sbox.Increase (1e-4 * sbox.Diam()); + + 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 Point<3> & p) +{ + int i; + Vec<3> grad; + Vec<3> rs, x; + Mat<3> jacobi, inv; + double alpha, beta, gamma, eta; + double sum; + int j; + + + rs(0) = f1->CalcFunctionValue (p); + rs(1) = f2->CalcFunctionValue (p); + rs(2) = f3->CalcFunctionValue (p); + + 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); + + alpha = 1; + if (fabs (Det (jacobi)) > 1e-8) + { + CalcInverse (jacobi, inv); + x = inv * rs; + + gamma = f1 -> HesseNorm() + f2 -> HesseNorm() + f3 -> HesseNorm(); + beta = 0; + for (i = 0; i < 3; i++) + { + sum = 0; + for (j = 0; j < 3; j++) + sum += fabs (inv(i,j)); + beta = max2 (beta, sum); + } + eta = Abs (x); + + alpha = beta * gamma * eta; + } + + return (alpha < 0.1); +} + + + + +bool SpecialPointCalculation :: +CrossPointDegenerated (const Surface * f1, + const Surface * f2, + const Surface * f3, + const BoxSphere<3> & box) const +{ + Mat<3> mat; + Vec<3> grad, g1, g2, g3; + double normprod; + + if (box.Diam() > relydegtest) return 0; + + f1->CalcGradient (box.Center(), g1); + normprod = Abs (g1); + + f2->CalcGradient (box.Center(), g2); + normprod *= Abs (g2); + + f3->CalcGradient (box.Center(), g3); + normprod *= Abs (g3); + + for (int i = 0; i < 3; i++) + { + mat(i,0) = g1(i); + mat(i,1) = g2(i); + mat(i,2) = g3(i); + } + + if (fabs (Det (mat)) < cpeps1 * normprod) + return 1; + else + return 0; +} + + + + + +void SpecialPointCalculation :: CrossPointNewton (const Surface * f1, + const Surface * f2, + const Surface * f3, Point<3> & p) +{ + int i; + Vec<3> g1, g2, g3; + Vec<3> rs, sol; + Mat<3> mat; + + 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); + /* + Transpose (g1, g2, g3); + SolveLinearSystem (g1, g2, g3, rs, sol); + */ + if (sol.Length() < 1e-12 && i > 1) i = 1; + + p -= sol; + } +} + + + + +/******* Tests for Point on edges **********************/ + + + + +bool SpecialPointCalculation :: +EdgeNewtonConvergence (const Surface * f1, const Surface * f2, + const Point<3> & p) +{ + int i; + Vec<3> g1, g2, sol; + Vec<2> vrs; + double alpha, beta, gamma, eta; + double sum; + Mat<2,3> mat; + Mat<3,2> inv; + int j; + + vrs(0) = f1->CalcFunctionValue (p); + vrs(1) = f2->CalcFunctionValue (p); + + f1->CalcGradient (p, g1); + f2->CalcGradient (p, g2); + + for (i = 0; i < 3; i++) + { + mat(0,i) = g1(i); + mat(1,i) = g2(i); + } + + alpha = 1; + + if ( fabs(g1 * g2) < (1 - 1e-8) * Abs (g1) * Abs (g2)) + { + CalcInverse (mat, inv); + sol = inv * vrs; + + // SolveLinearSystemLS (g1, g2, vrs, sol); + + gamma = f1 -> HesseNorm() + f2 -> HesseNorm(); + + /* + Vec<3> inv1, inv2; + PseudoInverse (g1, g2, inv1, inv2); + */ + + beta = 0; + for (i = 0; i < 3; i++) + for (j = 0; j < 2; j++) + beta += inv(i,j) * inv(i,j); + beta = sqrt (beta); + + // beta = inv1.Length() + inv2.Length(); + eta = Abs (sol); + alpha = beta * gamma * eta; + } + return (alpha < 0.1); +} + + + + +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(); + int i; + Vec<3> grad, g1, g2, sol; + Vec<2> vrs; + Mat<2,3> mat; + + i = 20; + while (i > 0) + { + if (Dist (p, box.Center()) > box.Diam()) + return 0; + + i--; + vrs(0) = f1->CalcFunctionValue (p); + vrs(1) = f2->CalcFunctionValue (p); + + f1->CalcGradient (p, g1); + f2->CalcGradient (p, g2); + + if ( fabs (g1 * g2) > (1 - 1e-10) * Abs (g1) * Abs (g2)) + return 1; + + for (int j = 0; j < 3; j++) + { + mat(0,j) = g1(j); + mat(1,j) = g2(j); + } + mat.Solve (vrs, sol); + // SolveLinearSystemLS (g1, g2, vrs, sol); + + if (Abs (sol) < 1e-12 && i > 1) i = 1; + p -= sol; + } + + return 0; + /* + return 0; + + static DenseMatrix jacobi(3); + Vec<3> grad, g1, g2, g3; + double normprod; + + if (box.Diam() > relydegtest) return 0; + + f1->CalcGradient (box.Center(), g1); + normprod = g1.Length(); + + f2->CalcGradient (box.Center(), g2); + normprod *= g2.Length(); + + if (fabs (g1 * g2) < 1e-8 * normprod) + return 1; + else + return 0; + */ +} + + + + + + +void SpecialPointCalculation :: EdgeNewton (const Surface * f1, + const Surface * f2, Point<3> & p) +{ + int i; + Vec<3> grad, g1, g2, sol; + Vec<2> vrs; + Mat<2,3> mat; + + i = 10; + while (i > 0) + { + i--; + vrs(0) = f1->CalcFunctionValue (p); + vrs(1) = f2->CalcFunctionValue (p); + + f1->CalcGradient (p, g1); + f2->CalcGradient (p, g2); + + for (int j = 0; j < 3; j++) + { + mat(0,j) = g1(j); + mat(1,j) = g2(j); + } + mat.Solve (vrs, sol); + // SolveLinearSystemLS (g1, g2, vrs, sol); + + if (Abs (sol) < 1e-12 && 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; + int j; + + 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 (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) +{ + int i; + + Vec<3> g1, g2, v, curv; + Vec<3> rs, x, y1, y2, y; + Mat<3> h1, h2; + Mat<3> jacobi; + + + if (dir < 1 || dir > 3) + { + cerr << "Error: Illegal extremdir" << endl; + return; + } + + 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); + + jacobi.Solve (rs, x); + /* + CalcInverse (jacobi, inv); + inv.Mult (rs, x); + */ + // (*testout) << "err = " << x.L2Norm() << endl; + + if (Abs (x) < 1e-12 && i > 1) + { + // (*testout) << "convergent in " << (10 - i) << " steps " << endl; + + i = 1; + } + + p -= x; + } + + if (Abs (x) > 1e-10) + { + (*testout) << "Error: extremum Newton not convergent" << endl; + (*testout) << "dir = " << dir << endl; + (*testout) << "p = " << p << endl; + (*testout) << "x = " << x << 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); + + /* + CalcInverse (a, inv); + inv.Mult (rs, x); // x .. Lagrangeparameter + */ + // (*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 0; + + points->Append (MeshPoint(p, layer)); + return 1; +} + + + + + + + +/* +void SpecialPointCalculation :: +AnalyzeSpecialPoints (const CSGeometry & ageometry, + ARRAY<Point<3> > & apoints, + ARRAY<SpecialPoint> & specpoints) +{ + int si, i, j, k, l, m, spi; + Solid * locsol; + ARRAY<int> surfind; + ARRAY<Vec<3>> normalvecs; + const Solid * sol; + Vec<3> t; + Point<3> p; + + ARRAY<int> specpoint2point; + specpoints.SetSize (0); + + (*testout) << "AnalyzeSpecialPoints" << endl; + + for (si = 1; si <= ageometry.GetNTopLevelObjects(); si++) + { + (*testout) << "main solid " << si << endl; + + sol = ageometry.GetTopLevelObject(si)->GetSolid(); + for (i = 1; i <= apoints.Size(); i++) + { + p = apoints.Get(i); + + sol -> TangentialSolid (p, locsol); + if (!locsol) continue; + + (*testout) << "Point " << apoints.Get(i) << endl; + + locsol -> GetSurfaceIndices (surfind); + for (j = surfind.Size(); j >= 1; j--) + if (fabs (ageometry.GetSurface(surfind.Get(j))-> + CalcFunctionValue (p)) > 1e-6) + surfind.DeleteElement (j); + + + + (*testout) << "Surfaces: "; + for (j = 1; j <= surfind.Size(); j++) + (*testout) << surfind.Get(j) << " "; + (*testout) << endl; + + normalvecs.SetSize(surfind.Size()); + for (j = 1; j <= surfind.Size(); j++) + ageometry.GetSurface(surfind.Get(j)) -> + GetNormalVector(apoints.Get(i), normalvecs.Elem(j)); + + for (j = 1; j <= normalvecs.Size() - 1; j ++) + for (k = j+1; k <= normalvecs.Size(); k++) + for (l = 1; l <= 2; l++) + { + t = Cross (normalvecs.Get(j), normalvecs.Get(k)); + if (t.Length2() < 1e-8) + { + cerr << "AnalyzePoint: Surfaces degenerated" << endl; + break; + } + t /= t.Length(); + if (l == 2) t *= -1; + + if (locsol -> Edge (apoints.Get(i), t)) + { + spi = 0; + for (m = 1; m <= specpoints.Size(); m++) + if (Dist2 (specpoints.Get(m).p, apoints.Get(i)) < 1e-8 + && (specpoints.Get(m).v - t).Length2() < 1e-8) + { + spi = m; + break; + } + if (!spi) + { + spi = specpoints.Append (SpecialPoint()); + specpoint2point.Append (i); + specpoints.Last().unconditional = 0; + } + specpoints.Elem(spi).p = apoints.Get(i); + specpoints.Elem(spi).v = t; + if (surfind.Size() >= 3) + specpoints.Elem(spi).unconditional = 1; + specpoints.Elem(spi).s1 = surfind.Get(j); + specpoints.Elem(spi).s2 = surfind.Get(k); + (*testout) << "spi = " << spi + << " uncond = " << specpoints.Get(spi).unconditional + << " t = " << t << endl; + } + + } + delete locsol; + } + } + + // if special point is unconditional on some solid, + // it must be unconditional everywhere: + + BitArray uncond (apoints.Size()); + uncond.Clear(); + + for (i = 1; i <= specpoints.Size(); i++) + if (specpoints.Get(i).unconditional) + uncond.Set (specpoint2point.Get(i)); + + for (i = 1; i <= specpoints.Size(); i++) + specpoints.Elem(i).unconditional = + uncond.Test (specpoint2point.Get(i)) ? 1 : 0; +} +*/ + + + +void SpecialPointCalculation :: +AnalyzeSpecialPoints (const CSGeometry & ageometry, + ARRAY<MeshPoint> & apoints, + ARRAY<SpecialPoint> & specpoints) +{ + int si, i, j, k, l, m, spi; + + Solid * locsol; + ARRAY<int> surfind; + ARRAY<int> surfind2; + + ARRAY<Vec<3> > normalvecs; + const Solid * sol; + const Surface * surf; + + Vec<3> t, nsurf; + Point<3> p; + + ARRAY<int> specpoint2point; + specpoints.SetSize (0); + + geometry = &ageometry; + + (*testout) << "AnalyzeSpecialPoints\n"; + + for (si = 0; si < ageometry.GetNTopLevelObjects(); si++) + { + (*testout) << "main solid " << si << "\n"; + + sol = ageometry.GetTopLevelObject(si)->GetSolid(); + surf = ageometry.GetTopLevelObject(si)->GetSurface(); + + for (i = 0; i < apoints.Size(); i++) + { + p = apoints[i]; + if (ageometry.GetTopLevelObject(si)->GetLayer() != + apoints[i].GetLayer()) + continue; + + // (*testout) << "Point " << apoints[i] << "\n"; + + sol -> TangentialSolid (p, locsol); + if (!locsol) continue; + + // get all surface indices, + if (surf) + { + locsol -> GetSurfaceIndices (surfind); + bool hassurf = 0; + for (m = 0; m < surfind.Size(); m++) + if (ageometry.GetSurface(surfind[m]) == surf) + hassurf = 1; + + if (!hassurf) + continue; + + surf->GetNormalVector (p, nsurf); + } + + // get independent surfaces of tangential solid + + BoxSphere<3> box(p,p); + box.Increase (1e-6); + box.CalcDiamCenter(); + ageometry.GetIndependentSurfaceIndices (locsol, box, surfind); + + + /* + locsol -> GetSurfaceIndices (surfind); + for (j = surfind.Size(); j >= 1; j--) + if (fabs (ageometry.GetSurface(surfind.Get(j))-> + CalcFunctionValue (p)) > 1e-6) + surfind.DeleteElement (j); + */ + + /* + (*testout) << "Surfaces: "; + for (j = 0; j < surfind.Size(); j++) + (*testout) << surfind[j] << " "; + (*testout) << "\n"; + */ + + + normalvecs.SetSize(surfind.Size()); + for (j = 0; j < surfind.Size(); j++) + ageometry.GetSurface(surfind[j]) -> + GetNormalVector(apoints[i], normalvecs[j]); + + for (j = 0; j < normalvecs.Size(); j++) + for (k = j+1; k < normalvecs.Size(); k++) + for (l = 1; l <= 2; l++) + { + t = Cross (normalvecs[j], normalvecs[k]); + if (Abs2 (t) < 1e-8) + { + cerr << "AnalyzePoint: Surfaces degenerated" << "\n"; + break; + } + t.Normalize(); + if (l == 2) t *= -1; + + // try tangential direction t + + // (*testout) << "check tangential " << t << "\n"; + + if (surf && fabs (nsurf * t) > 1e-6) + continue; + + if (!surf) + { + ageometry.GetIndependentSurfaceIndices + (locsol, p, t, surfind2); + + bool found1 = 0, found2 = 0; + for (int ii = 0; ii < surfind2.Size(); ii++) + { + if (surfind2[ii] == surfind[j]) + found1 = 1; + if (surfind2[ii] == surfind[k]) + found2 = 1; + } + if (!found1 || !found2) + continue; + } + + + bool isedge; + + // isedge = locsol -> Edge (apoints.Get(i), t); + + // edge must be on tangential surface + isedge = + locsol->VectorIn (p, t) && + !locsol->VectorStrictIn (p, t); + + // (*testout) << "isedge,1 = " << isedge << "\n"; + + // there must exist at least two different faces on edge + if (isedge) + { + int cnts = 0; + for (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; + + /* + (*testout) << "nv = " << normalvecs[m] << ", s = " << s << "\n"; + (*testout) << "t2a = " << t2a << ", t2b = " << t2b << "\n"; + (*testout) << "via = " + << locsol->VectorIn (p, t2a) << "/" + << locsol->VectorStrictIn (p, t2a); + (*testout) << "vib = " + << locsol->VectorIn (p, t2b) << "/" + << locsol->VectorStrictIn (p, t2b) << "\n"; + */ + + 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) + { + spi = -1; + for (m = 0; m < specpoints.Size(); m++) + if (Dist2 (specpoints[m].p, apoints[i]) < 1e-8 + && Abs2(specpoints[m].v - t) < 1e-8) + { + spi = m; + break; + } + if (spi == -1) + { + spi = specpoints.Append (SpecialPoint()) - 1; + specpoint2point.Append (i); + specpoints.Last().unconditional = 0; + } + specpoints[spi].p = apoints[i]; + specpoints[spi].v = t; + if (surfind.Size() >= 3) + specpoints[spi].unconditional = 1; + specpoints[spi].s1 = surfind[j]; + specpoints[spi].s2 = surfind[k]; + specpoints[spi].layer = apoints[i].GetLayer(); + for (int up = 0; up < geometry->GetNUserPoints(); up++) + if (Dist (geometry->GetUserPoint(up), apoints[i]) < 1e-10) + specpoints[spi].unconditional = 1; + + /* + (*testout) << "spi = " << spi + << " uncond = " << specpoints[spi].unconditional + << " t = " << t << "\n"; + */ + } + + } + delete locsol; + } + } + + // if special point is unconditional on some solid, + // it must be unconditional everywhere: + + BitArray uncond (apoints.Size()); + uncond.Clear(); + + for (i = 0; i < specpoints.Size(); i++) + if (specpoints[i].unconditional) + uncond.Set (specpoint2point[i]); + + for (i = 0; i < specpoints.Size(); i++) + specpoints[i].unconditional = + uncond.Test (specpoint2point[i]) ? 1 : 0; +} +} diff --git a/Netgen/libsrc/csg/specpoin.hpp b/Netgen/libsrc/csg/specpoin.hpp new file mode 100644 index 0000000000..244361e652 --- /dev/null +++ b/Netgen/libsrc/csg/specpoin.hpp @@ -0,0 +1,143 @@ +#ifndef FILE_SPECPOIN +#define FILE_SPECPOIN + + +/**************************************************************************/ +/* File: specpoin.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Okt. 95 */ +/**************************************************************************/ + +/* + +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; + + /// + SpecialPoint () : p(), v(), layer(0) + { ; } + + /// + SpecialPoint (const SpecialPoint & sp2); + + /// + SpecialPoint & operator= (const SpecialPoint & sp2); + + /// + void Print (ostream & str); + + + int GetLayer() const { return layer; } + + /// + bool HasSurfaces (int as1, int as2) const; +}; + + + +/// +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; + +public: + + /// + SpecialPointCalculation (); + + /// + 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 Point<3> & p); + /// + 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); +}; + +#endif + + diff --git a/Netgen/libsrc/csg/spline3d.cpp b/Netgen/libsrc/csg/spline3d.cpp new file mode 100644 index 0000000000..455493ad6f --- /dev/null +++ b/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; + 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/Netgen/libsrc/csg/spline3d.hpp b/Netgen/libsrc/csg/spline3d.hpp new file mode 100644 index 0000000000..753788459f --- /dev/null +++ b/Netgen/libsrc/csg/spline3d.hpp @@ -0,0 +1,92 @@ +/// +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/Netgen/libsrc/csg/surface.cpp b/Netgen/libsrc/csg/surface.cpp new file mode 100644 index 0000000000..2fd4064562 --- /dev/null +++ b/Netgen/libsrc/csg/surface.cpp @@ -0,0 +1,380 @@ +#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; +} + +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(); + // if (Inverse()) n *= -1; +} + +void Surface :: DefineTangentialPlane (const Point<3> & ap1, + const Point<3> & ap2) +{ + p1 = ap1; + p2 = ap2; + + GetNormalVector (p1, ez); + 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; + + GetNormalVector (p3d, n); + 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; + } +} + +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 (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(); + + cout << "cannot create primitive " << classname << endl; + return NULL; +} + + +Primitive * Primitive :: Copy () const +{ + cout << "Primitive called for baseclass" << endl; + return NULL; +} + + +void Primitive :: Transform (Transformation<3> & trans) +{ + cout << "transform called for baseclass" << endl; +} + + +INSOLID_TYPE Primitive :: +VecInSolid2 (const Point<3> & p, + const Vec<3> & v1, + const Vec<3> & v2, + double eps) const +{ + Point<3> hp = p + 1e-3 * v1 + 1e-5 * v2; + return PointInSolid (hp, 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 +{ + Vec<3> hv; + double hv1; + 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 +{ + Vec<3> hv; + double hv1, hv2; + + GetSurface(0).CalcGradient (p, hv); + + hv1 = v1 * hv; + if (hv1 <= -eps) + return IS_INSIDE; + if (hv1 >= eps) + return IS_OUTSIDE; + + hv2 = v2 * hv; + if (hv2 <= 0) + return IS_INSIDE; + else + return IS_OUTSIDE; +} + + + + +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); + + 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/Netgen/libsrc/csg/surface.hpp b/Netgen/libsrc/csg/surface.hpp new file mode 100644 index 0000000000..2738d5222d --- /dev/null +++ b/Netgen/libsrc/csg/surface.hpp @@ -0,0 +1,300 @@ +#ifndef FILE_SURFACE +#define FILE_SURFACE + +/**************************************************************************/ +/* File: surface.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 1. Dez. 95 */ +/**************************************************************************/ + + + + +// class DenseMatrix; +// class Box3dSphere; +class TriangleApproximation; + +/** + Basis class for implicit surface geometry. + This class is used for generation of surface meshes + in NETGEN as well as for mesh refinement in FEPP. + */ + + + + +class Surface +{ +protected: + /// invert normal vector + bool inverse; + /// maximal h in surface + double maxh; + /// name of surface + char * name; + /// boundary condition nr + int bcprop; + /// + +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 point 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; + //@} + + + /// Move Point p to closes point in surface + virtual void Project (Point<3> & p) const; + + + 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; + + /** + 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 { }; + +#ifdef MYGRAPH + /// + virtual void Plot (const class ROT3D & /* rot */) const { }; +#endif + }; + + +typedef enum { IS_OUTSIDE = 0, IS_INSIDE = 1, DOES_INTERSECT = 2} +INSOLID_TYPE; + + + + +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 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; + + + 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 (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 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/Netgen/libsrc/csg/triapprox.cpp b/Netgen/libsrc/csg/triapprox.cpp new file mode 100644 index 0000000000..b314855dae --- /dev/null +++ b/Netgen/libsrc/csg/triapprox.cpp @@ -0,0 +1,62 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> + + +namespace netgen +{ + +TriangleApproximation :: TriangleApproximation () +{ + ; +} + +int TriangleApproximation :: +AddTriangle (const TATriangle & tri, bool invert) +{ + trias.Append (tri); + if (invert) + { + trias.Last()[1] = tri[2]; + trias.Last()[2] = tri[1]; + } + return trias.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; + cnt++; + } + + for (i = 0; i < GetNT(); i++) + for (j = 0; j < 3; j++) + trias[i][j] = map[trias[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/Netgen/libsrc/csg/triapprox.hpp b/Netgen/libsrc/csg/triapprox.hpp new file mode 100644 index 0000000000..d7192a9a02 --- /dev/null +++ b/Netgen/libsrc/csg/triapprox.hpp @@ -0,0 +1,60 @@ +#ifndef FILE_TRIAPPROX +#define FILE_TRIAPPROX + +/**************************************************************************/ +/* File: triapprox.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 2. Mar. 98 */ +/**************************************************************************/ + +/** + 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 PNum (int i) const { return pi[i-1]; } + // int & PNum (int i) { return pi[i-1]; } + + 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> trias; + +public: + TriangleApproximation(); + int GetNP () const { return points.Size(); } + int GetNT () const { return trias.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 trias[i]; } + const Vec<3> & GetNormal (int i) const { return normals[i]; } + + void RemoveUnusedPoints (); + + friend class CSGeometry; +}; + +#endif diff --git a/Netgen/libsrc/general/Makefile b/Netgen/libsrc/general/Makefile new file mode 100644 index 0000000000..65a387a844 --- /dev/null +++ b/Netgen/libsrc/general/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for general purpose data types +# +src = array.cpp bitarray.cpp hashtabl.cpp symbolta.cpp table.cpp flags.cpp \ + spbita2d.cpp seti.cpp optmem.cpp sort.cpp mystring.cpp parthreads.cpp \ + moveablemem.cpp dynamicmem.cpp ngexception.cpp +# +lib = gen +libpath = libsrc/general +# +include ../makefile.inc + diff --git a/Netgen/libsrc/general/array.cpp b/Netgen/libsrc/general/array.cpp new file mode 100644 index 0000000000..e3bc3e6fdf --- /dev/null +++ b/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/Netgen/libsrc/general/array.hpp b/Netgen/libsrc/general/array.hpp new file mode 100644 index 0000000000..020a15ac34 --- /dev/null +++ b/Netgen/libsrc/general/array.hpp @@ -0,0 +1,471 @@ +#ifndef FILE_ARRAY +#define FILE_ARRAY + +/**************************************************************************/ +/* File: array.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + + +/** + 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; } + + + /// access array. + T & operator[] (int i) + { +#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. + const 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]; + } + + /// + 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]; + } + + /// + 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]; + } + + /// + 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 last element. check by macro CHECK_RANGE + T & Last () + { + return data[size-1]; + } + + /// access last element. check by macro CHECK_RANGE + const 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; + } +}; + + + + +// print array +template <class T, int BASE> +inline ostream & operator<< (ostream & s, const FlatArray<T,BASE> & a) +{ + for (int i = BASE; i < a.Size()+BASE; 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: + /// 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 = this->size; + ownmem = 1; + for (int i = BASE; i < this->size+BASE; i++) + (*this)[i] = a2[i]; + } + + + + /// if responsible, deletes memory + ~ARRAY() + { + if (ownmem) + delete [] this->data; + } + + /// Change logical size. If necessary, do reallocation. Keeps contents. + void SetSize(int nsize) + { + if (nsize > allocsize) + ReSize (nsize); + this->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 (this->size == allocsize) + ReSize (this->size+1); + this->data[this->size] = el; + this->size++; + return this->size; + } + + + /// Delete element i (0-based). Move last element to position i. + void Delete (int i) + { + 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 + + this->data[i-1] = this->data[this->size-1]; + this->size--; + } + + /// Delete last element. + void DeleteLast () + { + this->size--; + } + + /// Deallocate memory + void DeleteAll () + { + if (ownmem) + delete [] this->data; + this->data = 0; + this->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 < this->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 (this->data) + { + T * p = new T[nsize]; + + int mins = (nsize < this->size) ? nsize : this->size; + memcpy (p, this->data, mins * sizeof(T)); + + if (ownmem) + delete [] this->data; + ownmem = 1; + this->data = p; + } + else + { + this->data = new T[nsize]; + ownmem = 1; + } + + allocsize = nsize; + } +}; + + + +template <class T, int S> +class ArrayMem : public ARRAY<T> +{ + // T mem[S]; + char mem[S*sizeof(T)]; +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]))) + { + this->SetSize (asize); + } + + ArrayMem & operator= (const T & val) + { + ARRAY<T>::operator= (val); + return *this; + } +}; + + + + + + + + + + + +/// +template <class T> class MoveableArray +{ + int size; + int allocsize; + MoveableMem<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]; } + + /// + const T & operator[] (int i) const + { return ((const T*)data)[i]; } + + /// + 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; + } + + void SetName (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; +} + + + + + + + + +#endif + diff --git a/Netgen/libsrc/general/autoptr.hpp b/Netgen/libsrc/general/autoptr.hpp new file mode 100644 index 0000000000..b90841408b --- /dev/null +++ b/Netgen/libsrc/general/autoptr.hpp @@ -0,0 +1,31 @@ +#ifndef FILE_AUTOPTR +#define FILE_AUTOPTR + +/**************************************************************************/ +/* File: autoptr.hpp */ +/* Author: STL, Joachim Schoeberl */ +/* Date: 29. Dec. 02 */ +/**************************************************************************/ + +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/Netgen/libsrc/general/bitarray.cpp b/Netgen/libsrc/general/bitarray.cpp new file mode 100644 index 0000000000..0d03fd5c45 --- /dev/null +++ b/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/Netgen/libsrc/general/bitarray.hpp b/Netgen/libsrc/general/bitarray.hpp new file mode 100644 index 0000000000..380b78987e --- /dev/null +++ b/Netgen/libsrc/general/bitarray.hpp @@ -0,0 +1,207 @@ +#ifndef FILE_BitArray +#define FILE_BitArray + +/**************************************************************************/ +/* File: bitarray.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +#include <limits.h> + +/** + 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); + /// + inline INDEX Size () const; + + /// + void Set (); + /// + inline void Set (INDEX i); + /// + void Clear (); + /// + inline void Clear (INDEX i); + /// + inline int Test (INDEX i) const; + /// + void Invert (); + /// + void And (const BitArray & ba2); + /// + void Or (const BitArray & ba2); +private: + /// + inline unsigned char Mask (INDEX i) const; + /// + inline INDEX Addr (INDEX i) const; + + /// + 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 << 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 = 0; i < a.Size(); i++) + { + s << a.Test(i); + if (i % 40 == 0) s << "\n"; + } + if (a.Size() % 40 != 0) s << "\n"; + return s; +} + + +#endif diff --git a/Netgen/libsrc/general/dynamicmem.cpp b/Netgen/libsrc/general/dynamicmem.cpp new file mode 100644 index 0000000000..9cd1f3ad62 --- /dev/null +++ b/Netgen/libsrc/general/dynamicmem.cpp @@ -0,0 +1,117 @@ +#include <iostream> +#include <iomanip> + +#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]; + ptr = (char*)malloc (s); +} + +void BaseDynamicMem :: ReAlloc (size_t s) +{ + if (size == s) return; + + char * old = ptr; + // ptr = new char[s]; + ptr = (char*)malloc(s); + memmove (ptr, old, (s < size) ? s : size); + // delete old; + free (old); + size = s; +} + +void BaseDynamicMem :: Free () +{ + // delete ptr; + free (ptr); + ptr = 0; +} + +void BaseDynamicMem :: Swap (BaseDynamicMem & m2) +{ + int 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; + int mem = 0; + int cnt = 0; + while (p) + { + mem += p->size; + cnt++; + + cout << setw(10) << p->size << " Bytes"; + 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; +} + +} diff --git a/Netgen/libsrc/general/dynamicmem.hpp b/Netgen/libsrc/general/dynamicmem.hpp new file mode 100644 index 0000000000..501020988e --- /dev/null +++ b/Netgen/libsrc/general/dynamicmem.hpp @@ -0,0 +1,94 @@ +#ifndef FILE_DYNAMICMEM +#define FILE_DYNAMICMEM + +/**************************************************************************/ +/* File: dynamicmem.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 12. Feb. 2003 */ +/**************************************************************************/ + + + + +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 (); +}; + + +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/Netgen/libsrc/general/flags.cpp b/Netgen/libsrc/general/flags.cpp new file mode 100644 index 0000000000..962c8152e8 --- /dev/null +++ b/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 () + { + int i; + + for (i = 1; i <= strflags.Size(); i++) + delete strflags.Elem(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; + } + + int 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*> hstra(0); + return hstra; + } + } + + const ARRAY<double> & + Flags ::GetNumListFlag (const char * name) const + { + if (numlistflags.Used (name)) + return *numlistflags.Get(name); + else + { + static ARRAY<double> hnuma(0); + return hnuma; + } + } + + + int Flags :: StringFlagDefined (const char * name) const + { + return strflags.Used (name); + } + + int Flags :: NumFlagDefined (const char * name) const + { + return numflags.Used (name); + } + + int Flags :: StringListFlagDefined (const char * name) const + { + return strlistflags.Used (name); + } + + int 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/Netgen/libsrc/general/flags.hpp b/Netgen/libsrc/general/flags.hpp new file mode 100644 index 0000000000..7c62f7815b --- /dev/null +++ b/Netgen/libsrc/general/flags.hpp @@ -0,0 +1,83 @@ +#ifndef FILE_FLAGS +#define FILE_FLAGS + + +/**************************************************************************/ +/* File: flags.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 10. Oct. 96 */ +/**************************************************************************/ + +/** + 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: + /// + Flags (); + /// + ~Flags (); + + /// Deletes all flags + void DeleteFlags (); + /// Sets string flag, overwrite if exists + void SetFlag (const char * name, const char * val); + /// Sets numerical flag, overwrite if exists + void SetFlag (const char * name, double val); + /// Sets boolean flag + void SetFlag (const char * name); + /// Sets string arary falg + void SetFlag (const char * name, const ARRAY<char*> & val); + /// Sets double array flag + void SetFlag (const char * name, const ARRAY<double> & val); + + /// Save flags to file + void SaveFlags (const char * filename) const; + /// write flags to stream + void PrintFlags (ostream & ost) const; + /// Load flags from file + void LoadFlags (const char * filename); + /// set flag of form -name=hello -val=0.5 -defined + void SetCommandLineFlag (const char * st); + + /// Returns string flag, default value if not exists + const char * GetStringFlag (const char * name, const char * def) const; + /// Returns numerical flag, default value if not exists + double GetNumFlag (const char * name, double def) const; + /// Returns address of numerical flag, null if not exists + const double * GetNumFlagPtr (const char * name) const; + /// Returns address of numerical flag, null if not exists + double * GetNumFlagPtr (const char * name); + /// Returns boolean flag + int GetDefineFlag (const char * name) const; + /// Returns string list flag, empty array if not exist + const ARRAY<char*> & GetStringListFlag (const char * name) const; + /// Returns num list flag, empty array if not exist + const ARRAY<double> & GetNumListFlag (const char * name) const; + + + /// Test, if string flag is defined + int StringFlagDefined (const char * name) const; + /// Test, if num flag is defined + int NumFlagDefined (const char * name) const; + /// Test, if string list flag is defined + int StringListFlagDefined (const char * name) const; + /// Test, if num list flag is defined + int NumListFlagDefined (const char * name) const; +}; + +#endif + diff --git a/Netgen/libsrc/general/hashtabl.cpp b/Netgen/libsrc/general/hashtabl.cpp new file mode 100644 index 0000000000..3081298e24 --- /dev/null +++ b/Netgen/libsrc/general/hashtabl.cpp @@ -0,0 +1,293 @@ +/**************************************************************************/ +/* File: hashtabl.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + Abstract data type HASHTABLE +*/ + +#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 + { + int i; + for (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_2_CLOSED_HASHTABLE :: + BASE_INDEX_2_CLOSED_HASHTABLE (int size) + : hash(size) + { + hash.SetName ("i2-hashtable, hash"); + + invalid = -1; + int i; + for (i = 1; i <= size; i++) + hash.Elem(i).I1() = invalid; + } + + void BASE_INDEX_2_CLOSED_HASHTABLE :: + BaseSetSize (int size) + { + int i; + hash.SetSize(size); + for (i = 1; i <= size; i++) + hash.Elem(i).I1() = invalid; + } + + + int BASE_INDEX_2_CLOSED_HASHTABLE :: + Position2 (const INDEX_2 & ind) const + { + int i; + + 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; + + i = HashValue(ind); + 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; + } + } + } + + int BASE_INDEX_2_CLOSED_HASHTABLE :: UsedElements () const + { + int i, n = hash.Size(); + int cnt = 0; + for (i = 1; i <= n; i++) + if (hash.Get(i).I1() != invalid) + cnt++; + return cnt; + } + + + + + + + + + + + + BASE_INDEX_3_CLOSED_HASHTABLE :: + BASE_INDEX_3_CLOSED_HASHTABLE (int size) + : hash(size) + { + hash.SetName ("i3-hashtable, hash"); + + invalid = -1; + int i; + for (i = 1; i <= size; i++) + hash.Elem(i).I1() = invalid; + } + + void BASE_INDEX_3_CLOSED_HASHTABLE :: + BaseSetSize (int size) + { + int i; + hash.SetSize(size); + for (i = 1; i <= size; i++) + hash.Elem(i).I1() = invalid; + } + + + int BASE_INDEX_3_CLOSED_HASHTABLE :: + Position2 (const INDEX_3 & ind) const + { + int i; + + 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_3_CLOSED_HASHTABLE :: + PositionCreate2 (const INDEX_3 & ind, int & apos) + { + int i; + + i = HashValue(ind); + 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; + } + } + } + + int BASE_INDEX_3_CLOSED_HASHTABLE :: UsedElements () const + { + int i, n = hash.Size(); + int cnt = 0; + for (i = 1; i <= n; i++) + if (hash.Get(i).I1() != invalid) + cnt++; + return cnt; + } + + +} + diff --git a/Netgen/libsrc/general/hashtabl.hpp b/Netgen/libsrc/general/hashtabl.hpp new file mode 100644 index 0000000000..99d3257b84 --- /dev/null +++ b/Netgen/libsrc/general/hashtabl.hpp @@ -0,0 +1,931 @@ +#ifndef FILE_HASHTABL +#define FILE_HASHTABL + +/**************************************************************************/ +/* File: hashtabl.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/** + Abstract data type HASHTABLE. + Hash is done by one INDEX +*/ +class BASE_INDEX_HASHTABLE +{ +protected: + /// keys are stored in this table + TABLE<INDEX> 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> 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 int 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: + /// + inline INDEX_2_HASHTABLE (int size); + /// + void SetSize(int s) {cont.SetSize(s); BaseSetSize(s);} + /// + inline 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); + } + } + /// + inline const T & Get (const INDEX_2 & ahash) const; + /// + inline int Used (const INDEX_2 & ahash) const; + /// + inline int GetNBags () const; + /// + inline int GetBagSize (int bnr) const; + /// + inline void GetData (int bnr, int colnr, + INDEX_2 & ahash, T & acont) const; + /// + inline void PrintMemInfo (ostream & ost) const; +}; + + + +/// +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 int 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 (); +}; + + + + + + + + +/// 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; + } + /* + int pos = HashValue (ind); + if (hash.Get(pos) == ind) return pos; + return Position2 (ind); + */ + } + + // 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 int 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; + /// + 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); + } +}; + + + + + + + + + + + + + +class BASE_INDEX_3_CLOSED_HASHTABLE +{ +protected: + /// + MoveableArray<INDEX_3> hash; + /// + int invalid; +public: + /// + BASE_INDEX_3_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_3 & ind) const + { + return (ind.I1() + 15 * ind.I2() + 41 * ind.I3()) % hash.Size() + 1; + } + + int Position (const INDEX_3 & ind) const + { + int pos = HashValue (ind); + if (hash.Get(pos) == ind) return pos; + return Position2 (ind); + } + + // returns 1, if new postion is created + int PositionCreate (const INDEX_3 & 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_3 & ind) const; + int 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> cont; + +public: + /// + inline INDEX_3_CLOSED_HASHTABLE (int size); + /// + inline void Set (const INDEX_3 & ahash, const T & acont); + /// + inline const T & Get (const INDEX_3 & ahash) const; + /// + inline int Used (const INDEX_3 & ahash) const; + /// + inline void SetData (int pos, const INDEX_3 & ahash, const T & acont); + /// + inline void GetData (int pos, INDEX_3 & ahash, T & acont) const; + /// + inline void SetData (int pos, const T & acont); + /// + inline void GetData (int pos, T & acont) const; + /// + 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<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 int 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 int 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); + } + + + + + + + + + +/****************** INDEX_2_HASHTABLE ****************************/ + + +template<class T> +inline INDEX_2_HASHTABLE<T> :: INDEX_2_HASHTABLE (int size) + : BASE_INDEX_2_HASHTABLE (size), cont(size) + { + ; + } + +/* +template<class T> +inline void INDEX_2_HASHTABLE<T> :: 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.Add (bnr, ahash); + cont.Add (bnr, acont); + } + } +*/ + +template<class T> +inline const T & INDEX_2_HASHTABLE<T> :: Get (const INDEX_2 & ahash) const + { + int bnr = HashValue (ahash); + int pos = Position (bnr, ahash); + return cont.Get (bnr, pos); + } + +template<class T> +inline int INDEX_2_HASHTABLE<T> :: Used (const INDEX_2 & ahash) const + { + return (Position (HashValue (ahash), ahash)) ? 1 : 0; + } + +template<class T> +inline int INDEX_2_HASHTABLE<T> :: GetNBags () const + { + return cont.Size(); + } + +template<class T> +inline int INDEX_2_HASHTABLE<T> :: GetBagSize (int bnr) const + { + return cont.EntrySize (bnr); + } + +template<class T> +inline void INDEX_2_HASHTABLE<T> :: GetData (int bnr, int colnr, INDEX_2 & ahash, T & acont) const + { + ahash = hash.Get(bnr, colnr); + acont = cont.Get(bnr, colnr); + } + + + +template<class T> +inline void INDEX_2_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 int 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.Get(pos); +} + +template<class T> +inline int 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 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/Netgen/libsrc/general/moveablemem.cpp b/Netgen/libsrc/general/moveablemem.cpp new file mode 100644 index 0000000000..0e6f894dea --- /dev/null +++ b/Netgen/libsrc/general/moveablemem.cpp @@ -0,0 +1,241 @@ +#include <iostream> +#include <iomanip> + +#include <myadt.hpp> +using namespace std; +namespace netgen +{ + + NgMutex mem_mutex; + + size_t BaseMoveableMem::totalsize = 0; // 500000000; + size_t BaseMoveableMem::used = 0; + char * BaseMoveableMem::largeblock = 0; + + BaseMoveableMem * BaseMoveableMem::first = 0; + BaseMoveableMem * BaseMoveableMem::last = 0; + + + BaseMoveableMem :: BaseMoveableMem (size_t s) + { + // cout << "Construct object begin" << endl; + // Print (); + + prev = last; + next = 0; + + if (last) last->next = this; + last = this; + if (!first) first = this; + + size = 0; + + if (prev) + pos = prev->pos + prev->size; + else + pos = 0; + + ptr = 0; + name = 0; + + if (s) Alloc(s); +} + +BaseMoveableMem :: ~BaseMoveableMem () throw() +{ + Free(); + + if (next) next->prev = prev; + else last = prev; + if (prev) prev->next = next; + else first = next; + + delete name; +} + +void BaseMoveableMem :: SetName (const char * aname) +{ + delete name; + if (aname) + { + name = new char[strlen(aname)+1]; + strcpy (name, aname); + } +} + + +void BaseMoveableMem :: Alloc (size_t s) +{ + if (totalsize == 0) + { + size = s; + ptr = (char*) malloc(s); + return; + } + + + used += s - size; + + int r = s % 8; + if (r) s += 8-r; + if (prev) + pos = prev->pos + prev->size; + else + pos = 0; + size = s; + + if (next) + { + NgLock lock(mem_mutex); + lock.Lock(); + try + { + next->MoveTo (pos+size); + } + catch (NgException e) + { + lock.UnLock(); + throw NgException ("MoveableMem overflow"); + } + lock.UnLock(); + } + + if (size) + { + if (!largeblock) + { + cout << "moveable memory: allocate large block of " + << totalsize / 1048576 << " MB" << endl; + // largeblock = new char[totalsize]; + largeblock = (char*)malloc (totalsize); + } + ptr = largeblock+pos; + + if (pos + size > totalsize) + throw NgException ("MoveableMem overflow"); + } + else + ptr = 0; +} + +void BaseMoveableMem :: ReAlloc (size_t s) +{ + if (totalsize == 0) + { + if (size == s) return; + + char * old = ptr; + ptr = (char*)malloc(s); + memmove (ptr, old, (s < size) ? s : size); + free (old); + size = s; + return; + } + + Alloc (s); +} + +void BaseMoveableMem :: MoveTo (size_t newpos) +{ + // cout << "move block, oldpos = " << pos << "; newpos = " << newpos + // << ", size = " << size << endl; + static int move = 0; + + if (newpos + size > totalsize) + throw NgException ("MoveableMem overflow"); + if (newpos > pos) + { + if (next) next->MoveTo (newpos+size); + memmove (largeblock+newpos, largeblock+pos, size); + move += size; + } + else if (newpos < pos) + { + // cout << "move down: " << size << endl; + memmove (largeblock+newpos, largeblock+pos, size); + if (next) next->MoveTo (newpos+size); + move += size; + } + pos = newpos; + ptr = largeblock+pos; + // cout << "total move: " << move << endl; +} + +void BaseMoveableMem :: Free () throw() +{ + if (totalsize == 0) + { + free (ptr); + ptr = 0; + return; + } + + /* + cout << "free block, pos = " << pos << "size = " << size << endl; + cout << "before: " << endl; + Print(); + */ + used -= size; + if (next) + { + NgLock lock(mem_mutex); + lock.Lock(); + next->MoveTo (pos); + lock.UnLock(); + } + + size = 0; + ptr = 0; + // pos = 0; +} + +void BaseMoveableMem :: Swap (BaseMoveableMem & m2) throw() +{ + int hi; + BaseMoveableMem * hp; + char * cp; + hi = size; size = m2.size; m2.size = hi; + hi = pos; pos = m2.pos; m2.pos = hi; + /* + hp = prev; prev = m2.prev; m2.prev = hp; + hp = next; next = m2.next; m2.next = hp; + */ + cp = ptr; ptr = m2.ptr; m2.ptr = cp; + cp = name; name = m2.name; m2.name = cp; +} + + +void BaseMoveableMem :: Print () +{ + cout << "****************** Moveable Mem Report ****************" << endl; + BaseMoveableMem * p = first; + int mem = 0; + int cnt = 0; + while (p) + { + mem += p->size; + cnt++; + + cout << setw(10) << p->size << " Bytes"; + cout << ", pos = " << p->pos; + // cout << ", addr = " << p->ptr; + if (p->name) + cout << " in block " << p->name; + cout << endl; + + p = p->next; + } + + if (mem > 100000000) + cout << "memory in moveable arena: " << mem/1048576 << " MB" << endl; + else if (mem > 100000) + cout << "memory in moveable arena: " << mem/1024 << " kB" << endl; + else + cout << "memory in moveable arena: " << mem << " Bytes" << endl; + cout << "number of blocks: " << cnt << endl; + + cout << " used = " << used << endl; + // cout << "******************************************************" << endl; +} + +} diff --git a/Netgen/libsrc/general/moveablemem.hpp b/Netgen/libsrc/general/moveablemem.hpp new file mode 100644 index 0000000000..d156bb694c --- /dev/null +++ b/Netgen/libsrc/general/moveablemem.hpp @@ -0,0 +1,97 @@ +#ifndef FILE_MOVEABLEMEM +#define FILE_MOVEABLEMEM + +/**************************************************************************/ +/* File: moveablemem.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 12. Feb. 2003 */ +/**************************************************************************/ + + +extern NgMutex mem_mutex; + +class BaseMoveableMem +{ +public: + static size_t totalsize; + static size_t used; + +private: + static char * largeblock; + static BaseMoveableMem *first, *last; + + BaseMoveableMem *prev, *next; + size_t size, pos; + char * ptr; + char * name; + +protected: + BaseMoveableMem (size_t s = 0); + ~BaseMoveableMem () throw(); + void Alloc (size_t s); + void ReAlloc (size_t s); + void MoveTo (size_t newpos); + void Free () throw(); + char * Ptr() { return ptr; } + const char * Ptr() const { return ptr; } + void Swap (BaseMoveableMem & m2) throw(); +public: + void SetName (const char * aname); + static void Print (); +}; + + + + +template <typename T> +class MoveableMem : public BaseMoveableMem +{ +public: + MoveableMem (size_t s = 0) + : BaseMoveableMem (sizeof(T) * s) + { + ; + } + void Alloc (size_t s) + { + BaseMoveableMem::Alloc (sizeof(T) * s); + } + void ReAlloc (size_t s) + { + BaseMoveableMem::ReAlloc (sizeof(T) * s); + } + void Free () + { + BaseMoveableMem::Free (); + } + + const T * Ptr() const + { + return reinterpret_cast<const T*> (BaseMoveableMem::Ptr()); + } + + T * Ptr() + { + return reinterpret_cast<T*> (BaseMoveableMem::Ptr()); + } + + operator const T* () const + { + return reinterpret_cast<const T*> (BaseMoveableMem::Ptr()); + } + + operator T* () + { + return reinterpret_cast<T*> (BaseMoveableMem::Ptr()); + } + + void Swap (MoveableMem<T> & m2) + { + BaseMoveableMem::Swap (m2); + } +protected: + MoveableMem (const MoveableMem & m); + MoveableMem & operator= (const MoveableMem & m); +}; + +#endif diff --git a/Netgen/libsrc/general/myadt.hpp b/Netgen/libsrc/general/myadt.hpp new file mode 100644 index 0000000000..f74976d51f --- /dev/null +++ b/Netgen/libsrc/general/myadt.hpp @@ -0,0 +1,43 @@ +#ifndef FILE_MYADT +#define FILE_MYADT + +/**************************************************************************/ +/* File: myadt.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + include for all abstract data types +*/ + + + +#include <mystdlib.h> +#include <mydefs.hpp> + + +namespace netgen +{ +#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" +} + +#endif diff --git a/Netgen/libsrc/general/mystring.cpp b/Netgen/libsrc/general/mystring.cpp new file mode 100644 index 0000000000..b586202ba8 --- /dev/null +++ b/Netgen/libsrc/general/mystring.cpp @@ -0,0 +1,383 @@ + +//************************************************************** +// +// 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> + +/* +#include <iostream.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <fstream.h> +#include "mystring.hh" + + */ + +namespace netgen +{ + +void DefaultStringErrHandler() +{ + cerr << "Fehler : Bereichsüberschreitung bei Stringoperation\n" << flush; +} + +void (*MyStr::ErrHandler)() = DefaultStringErrHandler; + +MyStr::MyStr() +{ + length = 0; + // str = new char[1]; + str = shortstr; + str[0] = 0; +} + +MyStr::MyStr(const char *s) +{ + length = 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 = 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 = 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 = 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 = 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 = 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 std::string & st) +{ + length = 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; + } + int 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; + } +} + +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/Netgen/libsrc/general/mystring.hpp b/Netgen/libsrc/general/mystring.hpp new file mode 100644 index 0000000000..6517aad3fa --- /dev/null +++ b/Netgen/libsrc/general/mystring.hpp @@ -0,0 +1,193 @@ + +//************************************************************** +// +// 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 + +class Point3d; +class Vec3d; + +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: + MyStr(); + MyStr(const char *); + MyStr(char); + MyStr(const MyStr &); + MyStr(int); + MyStr(long); + MyStr(double); + MyStr(const Point3d& p); + MyStr(const Vec3d& p); + MyStr(const std::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(); + + //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() +{ + 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/Netgen/libsrc/general/ngexception.cpp b/Netgen/libsrc/general/ngexception.cpp new file mode 100644 index 0000000000..6746dd2521 --- /dev/null +++ b/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/Netgen/libsrc/general/ngexception.hpp b/Netgen/libsrc/general/ngexception.hpp new file mode 100644 index 0000000000..56c561aa8c --- /dev/null +++ b/Netgen/libsrc/general/ngexception.hpp @@ -0,0 +1,30 @@ +#ifndef FILE_NGEXCEPTION +#define FILE_NGEXCEPTION + +/**************************************************************************/ +/* File: ngexception.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 16. Jan. 2002 */ +/**************************************************************************/ + + +/// Base class for all ng exceptions +class NgException +{ + /// verbal description of exception + string what; +public: + /// + NgException (const string & s); + /// + virtual ~NgException (); + + /// append string to description + void Append (const string & s); + // void Append (const char * s); + + /// verbal description of exception + const string & What() const { return what; } +}; + +#endif diff --git a/Netgen/libsrc/general/optmem.cpp b/Netgen/libsrc/general/optmem.cpp new file mode 100644 index 0000000000..3247e7e38d --- /dev/null +++ b/Netgen/libsrc/general/optmem.cpp @@ -0,0 +1,59 @@ +/**************************************************************************/ +/* 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 (unsigned i = 0; i < bablocks.Size(); i++) + delete [] bablocks[i]; + } + + void * BlockAllocator :: Alloc () + { + // return new char[size]; + if (!freelist) + { + // 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/Netgen/libsrc/general/optmem.hpp b/Netgen/libsrc/general/optmem.hpp new file mode 100644 index 0000000000..a7a136c7c5 --- /dev/null +++ b/Netgen/libsrc/general/optmem.hpp @@ -0,0 +1,36 @@ +#ifndef FILE_OPTMEM +#define FILE_OPTMEM + +/**************************************************************************/ +/* File: optmem.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 04. Apr. 97 */ +/**************************************************************************/ + +/** + 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 (); + /// + void Free (void * p); +}; + + + +#endif diff --git a/Netgen/libsrc/general/parthreads.cpp b/Netgen/libsrc/general/parthreads.cpp new file mode 100644 index 0000000000..81e9d0b6cc --- /dev/null +++ b/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/Netgen/libsrc/general/parthreads.hpp b/Netgen/libsrc/general/parthreads.hpp new file mode 100644 index 0000000000..99dd017633 --- /dev/null +++ b/Netgen/libsrc/general/parthreads.hpp @@ -0,0 +1,126 @@ +#ifndef FILE_PARTHREADS +#define FILE_PARTHREADS + +/**************************************************************************/ +/* File: parthreads.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 22. Nov. 2000 */ +/**************************************************************************/ + +/* + Parallel thread, Mutex, +*/ + +#ifdef NO_PARALLEL_THREADS + +class NgMutex { }; + +class NgLock +{ +public: + NgLock (NgMutex & mut, bool lock = 0) { ; } + void Lock () { ; } + void UnLock () { ; } +}; + + +#else + +#ifdef WIN32 + +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; + } +}; + +#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 = 0) + : 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 = 1; + } + void UnLock () + { + pthread_mutex_unlock (&mut); + locked = 0; + } + /* + int TryLock () + { + return pthread_mutex_trylock (&mut); + } + */ +}; + +#endif + +#endif + +#endif diff --git a/Netgen/libsrc/general/seti.cpp b/Netgen/libsrc/general/seti.cpp new file mode 100644 index 0000000000..702337f076 --- /dev/null +++ b/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/Netgen/libsrc/general/seti.hpp b/Netgen/libsrc/general/seti.hpp new file mode 100644 index 0000000000..4ca0b8eb4e --- /dev/null +++ b/Netgen/libsrc/general/seti.hpp @@ -0,0 +1,45 @@ +#ifndef FILE_SETI +#define FILE_SETI + + +/**************************************************************************/ +/* File: seti.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Mar. 98 */ +/**************************************************************************/ + +/** + 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> & Array() { return set; } +}; + +#endif + diff --git a/Netgen/libsrc/general/sort.cpp b/Netgen/libsrc/general/sort.cpp new file mode 100644 index 0000000000..b4f2c8c0b4 --- /dev/null +++ b/Netgen/libsrc/general/sort.cpp @@ -0,0 +1,74 @@ +/**************************************************************************/ +/* File: sort.cc */ +/* Author: Joachim Schoeberl */ +/* Date: 07. Jan. 00 */ +/**************************************************************************/ + +/* + Sorting +*/ + + +#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 QickSortRec (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) QickSortRec (values, order, left, j); + if (i < right) QickSortRec (values, order, i, right); +} + +void QickSort (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; + + QickSortRec (values, order, 1, order.Size()); +} +} diff --git a/Netgen/libsrc/general/sort.hpp b/Netgen/libsrc/general/sort.hpp new file mode 100644 index 0000000000..63a85dad45 --- /dev/null +++ b/Netgen/libsrc/general/sort.hpp @@ -0,0 +1,18 @@ +#ifndef FILE_SORT +#define FILE_SORT + +/**************************************************************************/ +/* File: sort.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 07. Jan. 00 */ +/**************************************************************************/ + +// order(i) is sorted index of element i +extern void Sort (const ARRAY<double> & values, + ARRAY<int> & order); + +extern void QickSort (const ARRAY<double> & values, + ARRAY<int> & order); + + +#endif diff --git a/Netgen/libsrc/general/spbita2d.cpp b/Netgen/libsrc/general/spbita2d.cpp new file mode 100644 index 0000000000..e1e80e2cad --- /dev/null +++ b/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/Netgen/libsrc/general/spbita2d.hpp b/Netgen/libsrc/general/spbita2d.hpp new file mode 100644 index 0000000000..db656653b1 --- /dev/null +++ b/Netgen/libsrc/general/spbita2d.hpp @@ -0,0 +1,56 @@ +#ifndef FILE_SPBITA2D +#define FILE_SPBITA2D + +/**************************************************************************/ +/* File: spbita2d.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/** + Implementation of sparse 2 dimensional bitarray +*/ + + +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/Netgen/libsrc/general/stack.hpp b/Netgen/libsrc/general/stack.hpp new file mode 100644 index 0000000000..db8dfad266 --- /dev/null +++ b/Netgen/libsrc/general/stack.hpp @@ -0,0 +1,112 @@ +#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" + + +/// +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/Netgen/libsrc/general/symbolta.cpp b/Netgen/libsrc/general/symbolta.cpp new file mode 100644 index 0000000000..b02daa65dc --- /dev/null +++ b/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/Netgen/libsrc/general/symbolta.hpp b/Netgen/libsrc/general/symbolta.hpp new file mode 100644 index 0000000000..e429c7d19b --- /dev/null +++ b/Netgen/libsrc/general/symbolta.hpp @@ -0,0 +1,158 @@ +#ifndef FILE_SYMBOLTA +#define FILE_SYMBOLTA + + +/**************************************************************************/ +/* File: symbolta.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/** + 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 +{ + /// 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 int 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; + 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 int SYMBOLTABLE<T> :: Used (const char * name) const + { + return (Index(name)) ? 1 : 0; + } + +template <class T> +inline void SYMBOLTABLE<T> :: DeleteAll () + { + DelNames(); + data.DeleteAll(); + } + + +#endif diff --git a/Netgen/libsrc/general/table.cpp b/Netgen/libsrc/general/table.cpp new file mode 100644 index 0000000000..7dcd5557d3 --- /dev/null +++ b/Netgen/libsrc/general/table.cpp @@ -0,0 +1,192 @@ +/**************************************************************************/ +/* 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) + { + int i; + for (i = 0; i < data.Size(); i++) + delete [] (char*)data[i].col; + + data.SetSize(size); + for (i = 0; i < size; i++) + { + data[i].maxsize = 0; + data[i].size = 0; + data[i].col = NULL; + } + } + + void BASE_TABLE :: IncSize2 (int i, int elsize) + { + if (i < 1 || i > data.Size()) + { + MyError ("BASE_TABLE::Inc: Out of range"); + return; + } + + linestruct & line = data.Elem (i); + + if (line.size == line.maxsize) + { + /* + static int totalloc = 0, cnt = 0; + totalloc += (line.maxsize+5) * elsize; + cnt ++; + + if (cnt % 100000 == 0) + cout << "base_table: total alloc = " << totalloc << endl; + */ + + void * p = new char [(line.maxsize+5) * elsize]; + // mem_total_alloc_table += (line.maxsize+5) * elsize; + + + if (!p) + { + MyError ("BASE_TABLE::Inc: Out of memory"); + return; + } + + memcpy (p, line.col, line.maxsize * elsize); + delete [] (char*)line.col; + line.col = p; + line.maxsize += 5; + } + + line.size++; + } + + void BASE_TABLE :: DecSize (int i) + { + if (i < 1 || i > data.Size()) + { + MyError ("BASE_TABLE::Dec: Out of range"); + return; + } + + linestruct & line = data.Elem (i); + + if (line.size == 0) + { + MyError ("BASE_TABLE::Dec: EntrySize < 0"); + return; + } + + line.size--; + } + + + /* + void BASE_TABLE :: IncSizePrepare (int i) + { + data.Elem(i).maxsize++; + } + */ + + + void BASE_TABLE :: AllocateElementsOneBlock (int elemsize) + { + int i, cnt = 0; + int n = data.Size(); + + for (i = 1; i <= n; i++) + cnt += data.Get(i).maxsize; + oneblock = new char[elemsize * cnt]; + // mem_total_alloc_table += elemsize * cnt; + + // cout << "Allocate oneblock, mem = " << (elemsize * cnt) << endl; + + cnt = 0; + for (i = 1; i <= n; i++) + { + data.Elem(i).size = 0; + + data.Elem(i).col = &oneblock[elemsize * cnt]; + cnt += data.Elem(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; + } + +} diff --git a/Netgen/libsrc/general/table.hpp b/Netgen/libsrc/general/table.hpp new file mode 100644 index 0000000000..21c6d41a60 --- /dev/null +++ b/Netgen/libsrc/general/table.hpp @@ -0,0 +1,202 @@ +#ifndef FILE_TABLE +#define FILE_TABLE + +/**************************************************************************/ +/* File: table.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/// 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 IncSize (int i, int elsize) + { + if (data.Elem(i).size < data.Elem(i).maxsize) + data.Elem(i).size++; + else + IncSize2 (i, elsize); + } + /// + void IncSize2 (int i, int elsize); + + void DecSize (int i); + + /// + void AllocateElementsOneBlock (int elemsize); + + int AllocatedElements () const; + int UsedElements () const; +}; + + + + + + + +/** + 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 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); + } + + + /// Inserts element acont into row i, 1-based. Does not test if already used. + inline void Add (int i, const T & acont) + { + IncSize (i-BASE+1, sizeof (T)); + ((T*)data[i-BASE].col)[data[i-BASE].size-1] = acont; + } + + /// + void IncSizePrepare (int i) + { + data[i-BASE].maxsize++; + } + + + /// Inserts element acont into row i, 1-based. Does not test if already used. + inline void Add1 (int i, const T & acont) + { + IncSize (i, sizeof (T)); + ((T*)data.Elem(i).col)[data.Elem(i).size-1] = acont; + } + + /// Inserts element acont into row i. Does not test if already used, assumes to have mem + inline void AddSave (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, 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, TABLE<T,BASE> & table) +{ + for (int i = BASE; i < table.Size()+BASE; i++) + { + ost << i << ": "; + FlatArray<T> row = table[i]; + for (int j = 0; j < row.Size(); j++) + ost << row[j] << " "; + ost << endl; + } + return ost; +} + +#endif + diff --git a/Netgen/libsrc/general/template.hpp b/Netgen/libsrc/general/template.hpp new file mode 100644 index 0000000000..47c7a1ad2e --- /dev/null +++ b/Netgen/libsrc/general/template.hpp @@ -0,0 +1,422 @@ +#ifndef FILE_TEMPLATE +#define FILE_TEMPLATE + +/**************************************************************************/ +/* File: template.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + 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 */ +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 */ +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]; } + + /// + void Sort () + { + if (i[0] > i[1]) + { + INDEX hi = i[0]; + i[0] = i[1]; + i[1] = hi; + } + } + /// + 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]; } + + /// + void 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]); + } + + /// + 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); +}; + + + + + + + + + + + + +/// +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/Netgen/libsrc/geom2d/Makefile b/Netgen/libsrc/geom2d/Makefile new file mode 100644 index 0000000000..8371fa19e7 --- /dev/null +++ b/Netgen/libsrc/geom2d/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for geometric library +# +src = spline2d.cpp geom2dmesh.cpp splinegeometry2.cpp genmesh2d.cpp +# +lib = geom2d +libpath = libsrc/geom2d +# +# +include ../makefile.inc +# + diff --git a/Netgen/libsrc/geom2d/genmesh2d.cpp b/Netgen/libsrc/geom2d/genmesh2d.cpp new file mode 100644 index 0000000000..db31208940 --- /dev/null +++ b/Netgen/libsrc/geom2d/genmesh2d.cpp @@ -0,0 +1,121 @@ +#include <mystdlib.h> +#include <csg.hpp> +#include <geometry2d.hpp> +#include "meshing.hpp" + +namespace netgen +{ + + // static ARRAY<Point<2> > points2; + // static ARRAY<int> lp1, lp2; + + + extern void Optimize2d (Mesh & mesh, MeshingParameters & mp); + + + + + void MeshFromSpline2D (SplineGeometry2d & geometry, + Mesh *& mesh, + MeshingParameters & mp) + { + int i, j, domnr; + double elto0, minx, miny, maxx, maxy; + + PointIndex pi; + SegmentIndex si; + SurfaceElementIndex sei; + + double h = mp.maxh; + + Box<2> bbox; + geometry.GetBoundingBox (bbox); + + if (bbox.Diam() < h) + { + h = bbox.Diam(); + mp.maxh = h; + } + + mesh = new Mesh; + mesh->SetDimension (2); + PrintMessage (1, "Generate Mesh from spline geometry"); + + geometry.PartitionBoundary (h, *mesh); + + int maxdomnr = 0; + for (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 (i = 1; i <= maxdomnr; i++) + mesh->AddFaceDescriptor (FaceDescriptor (i, 0, 0, i)); + + 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(); + + int bnp = mesh->GetNP(); // boundary points + + for (domnr = 1; domnr <= maxdomnr; domnr++) + { + PrintMessage (3, "Meshing domain ", domnr, " / ", maxdomnr); + + int oldnf = mesh->GetNSE(); + + Meshing2 meshing (Box3d (pmin, pmax)); + + for (pi = PointIndex::BASE; + pi < bnp+PointIndex::BASE; pi++) + meshing.AddPoint ( (*mesh)[pi], pi); + + + PointGeomInfo gi; + gi.trignum = 1; + for (si = 0; si < mesh->GetNSeg(); si++) + { + if ( (*mesh)[si].domin == domnr) + meshing.AddBoundaryElement ( (*mesh)[si].p1 + 1 - PointIndex::BASE, + (*mesh)[si].p2 + 1 - PointIndex::BASE, gi, gi); + if ( (*mesh)[si].domout == domnr) + meshing.AddBoundaryElement ( (*mesh)[si].p2 + 1 - PointIndex::BASE, + (*mesh)[si].p1 + 1 - PointIndex::BASE, gi, gi); + } + + + mparam.checkoverlap = 0; + meshing.GenerateMesh (*mesh, h, domnr); + + for (sei = oldnf; sei < mesh->GetNSE(); sei++) + (*mesh)[sei].SetIndex (domnr); + } + + + 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(); + } + + +} diff --git a/Netgen/libsrc/geom2d/geom2dmesh.cpp b/Netgen/libsrc/geom2d/geom2dmesh.cpp new file mode 100644 index 0000000000..3ca3275d29 --- /dev/null +++ b/Netgen/libsrc/geom2d/geom2dmesh.cpp @@ -0,0 +1,96 @@ +#include <mystdlib.h> + +#include <csg.hpp> +#include <geometry2d.hpp> +#include <meshing.hpp> + +namespace netgen +{ + +Refinement2d :: Refinement2d (const SplineGeometry2d & ageometry) + : Refinement(), geometry(ageometry) +{ + ; +} + +Refinement2d :: ~Refinement2d () +{ + ; +} + + + +void Refinement2d :: +PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi, + const PointGeomInfo & gi1, + const PointGeomInfo & gi2, + Point3d & newp, PointGeomInfo & newgi) +{ + newp = p1+secpoint*(p2-p1); + newgi.trignum = 1; + /* + if (surfi) + { + // (*testout) << "surfi1 = " << surfi << endl; + // (*testout) << "np = " << newp << endl; + geometry.GetSurface (surfi) -> Project (newp); + newgi.trignum = 1; + // (*testout) << "np2 = " << newp << endl; + } + */ +} + + + +void Refinement2d :: +PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi1, int surfi2, + const EdgePointGeomInfo & ap1, + const EdgePointGeomInfo & ap2, + Point3d & newp, EdgePointGeomInfo & newgi) +{ + Point<2> p2d; + + p2d = geometry.GetSplines().Get(ap1.edgenr) -> + GetPoint (((1-secpoint)*ap1.dist+secpoint*ap2.dist)); + + +/* + + // test routine: general function on first edge + + double x = secpoint; + if (ap1.edgenr == 1) + p2d = Point<2>((1-secpoint),fabs(x-0.5) < 0.2 ? (1+cos((x-0.5)*M_PI/0.2))*0.1 : 0); + +*/ + + // (*testout) << "refine 2d line, ap1.dist, ap2.dist = " << ap1.dist << ", " << ap2.dist << endl; + // (*testout) << "p1, p2 = " << p1 << p2 << ", newp = " << p2d << endl; + + // newp = Center (p1, p2); + newp = Point3d (p2d(0), p2d(1), 0); + newgi.edgenr = ap1.edgenr; + newgi.dist = ((1-secpoint)*ap1.dist+secpoint*ap2.dist); + + /* + if (surfi1 && surfi2 && surfi1 != surfi2) + { + // (*testout) << "surfi1 = " << surfi1 << " surfi2 = " << surfi2 << endl; + // (*testout) << "np = " << newp << endl; + // geometry.GetSurface (surfi1) -> Project (newp); + ProjectToEdge (geometry.GetSurface(surfi1), + geometry.GetSurface(surfi2), + newp); + newgi.edgenr = 1; + // (*testout) << "np2 = " << newp << endl; + } + else if (surfi1) + { + geometry.GetSurface (surfi1) -> Project (newp); + } + */ +}; + +} diff --git a/Netgen/libsrc/geom2d/geom2dmesh.hpp b/Netgen/libsrc/geom2d/geom2dmesh.hpp new file mode 100644 index 0000000000..6912cd7752 --- /dev/null +++ b/Netgen/libsrc/geom2d/geom2dmesh.hpp @@ -0,0 +1,38 @@ +#ifndef FILE_GEOM2DMESH +#define FILE_GEOM2DMESH + +/**************************************************************************/ +/* File: geom2dmesh.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 22. Jan. 01 */ +/**************************************************************************/ + + +class Refinement2d : public Refinement +{ + const SplineGeometry2d & geometry; + +public: + Refinement2d (const SplineGeometry2d & ageometry); + virtual ~Refinement2d (); + + virtual void PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi, + const PointGeomInfo & gi1, + const PointGeomInfo & gi2, + Point3d & newp, PointGeomInfo & newgi); + + virtual void PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi1, int surfi2, + const EdgePointGeomInfo & ap1, + const EdgePointGeomInfo & ap2, + Point3d & newp, EdgePointGeomInfo & newgi); + +}; + + + + + + +#endif diff --git a/Netgen/libsrc/geom2d/geometry2d.hpp b/Netgen/libsrc/geom2d/geometry2d.hpp new file mode 100644 index 0000000000..80d276e340 --- /dev/null +++ b/Netgen/libsrc/geom2d/geometry2d.hpp @@ -0,0 +1,20 @@ +#ifndef FILE_GEOMETRY2D +#define FILE_GEOMETRY2D + +/* *************************************************************************/ +/* File: geometry2d.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Jul. 02 */ +/* *************************************************************************/ + +#include <myadt.hpp> +#include <gprim.hpp> + +namespace netgen +{ +#include "spline2d.hpp" +#include "splinegeometry2.hpp" +#include "geom2dmesh.hpp" +} + +#endif diff --git a/Netgen/libsrc/geom2d/spline2d.cpp b/Netgen/libsrc/geom2d/spline2d.cpp new file mode 100644 index 0000000000..18c0362f41 --- /dev/null +++ b/Netgen/libsrc/geom2d/spline2d.cpp @@ -0,0 +1,350 @@ +/* + +2d Spline curve for Mesh generator + +*/ + +#include <mystdlib.h> +#include <csg.hpp> +#include <linalg.hpp> +#include <meshing.hpp> + +namespace netgen +{ +#include "spline2d.hpp" + + +void CalcPartition (double l, double h, double r1, double r2, + double ra, double elto0, ARRAY<double> & points); + + + +// calculates length of spline-curve +double SplineSegment :: Length () const +{ + Point<2> p, pold; + + int i, n = 100; + double dt = 1.0 / n; + + pold = GetPoint (0); + + double l = 0; + for (i = 1; i <= n; i++) + { + p = GetPoint (i * dt); + l += Dist (p, pold); + pold = p; + } + return l; +} + + + +// partitionizes spline curve +void SplineSegment :: Partition (double h, double elto0, + Mesh & mesh, int segnr) const +{ + int i, j; + double l, r1, r2, ra; + double lold, dt, frac; + int n = 100; + Point<2> p, pold, mark, oldmark; + ARRAY<double> curvepoints; + double edgelength, edgelengthold; + l = Length(); + + r1 = StartPI().refatpoint; + r2 = EndPI().refatpoint; + ra = reffak; + + // cout << "Partition, l = " << l << ", h = " << h << endl; + CalcPartition (l, h, r1, r2, ra, elto0, curvepoints); + // cout << "curvepoints = " << curvepoints << endl; + + dt = 1.0 / n; + + l = 0; + j = 1; + + pold = GetPoint (0); + lold = 0; + oldmark = pold; + edgelengthold = 0; + + for (i = 1; i <= n; i++) + { + p = GetPoint (i*dt); + l = lold + Dist (p, pold); + while (j < curvepoints.Size() && (l >= curvepoints[j] || i == n)) + { + frac = (curvepoints[j]-lold) / (l-lold); + mark = pold + frac * (p-pold); + edgelength = i*dt + (frac-1)*dt; + { + PointIndex pi1 = -1, pi2 = -1; + + Point3d mark3(mark(0), mark(1), 0); + Point3d oldmark3(oldmark(0), oldmark(1), 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); + if (pi2 == -1) pi2 = mesh.AddPoint(mark3); + + // cout << "pi1 = " << pi1 << endl; + // cout << "pi2 = " << pi2 << endl; + + Segment seg; + seg.edgenr = segnr; + seg.si = bc; // segnr; + seg.p1 = pi1; + seg.p2 = pi2; + seg.domin = leftdom; + seg.domout = rightdom; + seg.epgeominfo[0].edgenr = segnr; + seg.epgeominfo[0].dist = edgelengthold; + seg.epgeominfo[1].edgenr = segnr; + seg.epgeominfo[1].dist = edgelength; + + mesh.AddSegment (seg); + } + + oldmark = mark; + edgelengthold = edgelength; + j++; + } + + pold = p; + lold = l; + } +} + + +void SplineSegment :: GetPoints (int n, ARRAY<Point<2> > & points) +{ + points.SetSize (n); + if (n >= 2) + for (int i = 0; i < n; i++) + points[i] = GetPoint(double(i) / (n-1)); +} + + + +/* + Implementation of line-segment from p1 to p2 +*/ + + +LineSegment :: LineSegment (const GeomPoint2d & ap1, + const GeomPoint2d & ap2) + : p1(ap1), p2(ap2) +{ + ; +} + + +Point<2> LineSegment :: GetPoint (double t) const +{ + return p1 + t * (p2 - p1); +} + +double LineSegment :: Length () const +{ + return Dist (p1, p2); +} + + +void LineSegment :: PrintCoeff (ostream & ost) const +{ + double dx = p2(0) - p1(0); + double dy = p2(1) - p1(1); + ost << "0 0 0 " << dy << " " << -dx << " " + << dx * p1(1) - dy * p1(0) << endl; +} + + + + + +SplineSegment3 :: SplineSegment3 (const GeomPoint2d & ap1, + const GeomPoint2d & ap2, + const GeomPoint2d & ap3) + : p1(ap1), p2(ap2), p3(ap3) +{ + ; +} + +Point<2> SplineSegment3 :: GetPoint (double t) const +{ + double x, y, w; + double b1, b2, b3; + + b1 = (1-t)*(1-t); + b2 = sqrt(2.0) * 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; + + return Point<2> (x/w, y/w); +} + + +void SplineSegment3 :: PrintCoeff (ostream & ost) const +{ + double t; + int i; + Point<2> p; + DenseMatrix a(6, 6); + DenseMatrix ata(6, 6); + Vector u(6), f(6); + + // ata.SetSymmetric(1); + + t = 0; + for (i = 1; i <= 5; i++, t += 0.25) + { + p = GetPoint (t); + a.Elem(i, 1) = p(0) * p(0); + a.Elem(i, 2) = p(1) * p(1); + a.Elem(i, 3) = p(0) * p(1); + a.Elem(i, 4) = p(0); + a.Elem(i, 5) = p(1); + a.Elem(i, 6) = 1; + } + a.Elem(6, 1) = 1; + + CalcAtA (a, ata); + + u = 0; + u.Elem(6) = 1; + a.MultTrans (u, f); + ata.Solve (f, u); + + for (i = 1; i <= 6; i++) + ost << u.Get(i) << " "; + ost << endl; +} + + + + +//######################################################################## +// circlesegment + +CircleSegment :: CircleSegment (const GeomPoint2d & ap1, + const GeomPoint2d & ap2, + const GeomPoint2d & ap3) + : p1(ap1), p2(ap2), p3(ap3) +{ + Vec<2> v1,v2; + + v1 = p1 - p2; + v2 = p3 - p2; + + Point<2> p1t(p1(0)+v1[1], p1(1)-v1[0]); + Point<2> p2t(p3(0)+v2[1], p3(1)-v2[0]); + Line2d g1t(p1, p1t), g2t(p3, p2t); + + pm = CrossPoint (g1t,g2t); + radius = Dist(pm,StartPI()); + w1 = Angle(Vec2d (p1 - pm)); + w3 = Angle(Vec2d (p3 - pm)); + if ( fabs(w3-w1) > M_PI ) + { + if ( w3>M_PI ) w3 -= 2*M_PI; + if ( w1>M_PI ) w1 -= 2*M_PI; + } +} + +Point<2> CircleSegment :: GetPoint (double t) const +{ + if (t >= 1.0) { return p3; } + + double phi = StartAngle() + t*(EndAngle()-StartAngle()); + Vec2d tmp(cos(phi),sin(phi)); + + return pm + Radius()*tmp; +} + +void CircleSegment :: PrintCoeff (ostream & ost) const +{ + double a,b,c,d,e,f; + + a = b = 1.0; + c = 0.0; + d = -2.0 * pm[0]; + e = -2.0 * pm[1]; + f = sqr(pm[0]) + sqr(pm[1]) - sqr(Radius()); + + ost << a << " " << b << " " << c << " " << d << " " << e << " " << f ; + ost << endl; +} + + + + + + +//######################################################################## + + + + +void CalcPartition (double l, double h, double r1, double r2, + double ra, double elto0, ARRAY<double> & points) +{ + 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 (h/ra, t/elto0 + h/r1, (l-t)/elto0 + h/r2); + 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 (h/ra, t/elto0 + h/r1, (l-t)/elto0 + h/r2); + + 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); +} + + +} diff --git a/Netgen/libsrc/geom2d/spline2d.hpp b/Netgen/libsrc/geom2d/spline2d.hpp new file mode 100644 index 0000000000..bdd33d736b --- /dev/null +++ b/Netgen/libsrc/geom2d/spline2d.hpp @@ -0,0 +1,167 @@ +#ifndef FILE_SPLINE2D +#define FILE_SPLINE2D + +/**************************************************************************/ +/* File: spline2d.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 24. Jul. 96 */ +/**************************************************************************/ + + +/* + Spline curves for 2D mesh generation + */ + + +/// Geometry point +class GeomPoint2d : public Point<2> +{ +public: + /// refinement to point + double refatpoint; + + 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; + + /// 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, 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 */ + virtual void PrintCoeff (ostream & ost) const = 0; + + virtual void GetPoints (int n, ARRAY<Point<2> > & points); +}; + + +/// 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; +}; + + +/// 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; +}; + + +// 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; + /// + double Radius() const { return radius; } + /// + double StartAngle() const { return w1; } + /// + double EndAngle() const { return w3; } +}; + + +// Gundolf Haase 8/26/97 +/// elliptic curve with one axe parallel to line {P1,P2} +/* +class ellipsegment3 : public SplineSegment +{ + /// + GeomPoint2d *p1, *p2, *p3; +public: + /// + SplineSegment3 (GeomPoint2d * ap1, GeomPoint2d * ap2, GeomPoint2d * ap3); + /// + virtual Point<2> GetPoint (double t) const; + /// + virtual GeomPoint2d * StartPI () const { return p1; }; + /// + virtual GeomPoint2d * EndPI () const { return p3; } + /// + virtual void PrintCoeff (ostream & ost) const; +}; +*/ + + + + +#endif diff --git a/Netgen/libsrc/geom2d/splinegeometry2.cpp b/Netgen/libsrc/geom2d/splinegeometry2.cpp new file mode 100644 index 0000000000..921e22a295 --- /dev/null +++ b/Netgen/libsrc/geom2d/splinegeometry2.cpp @@ -0,0 +1,224 @@ +/* + +2d Spline curve for Mesh generator + +*/ + +#include <mystdlib.h> +#include <csg.hpp> +#include <linalg.hpp> +#include <meshing.hpp> + + +namespace netgen + +{ + +#include "spline2d.hpp" +#include "splinegeometry2.hpp" + + + + + +void SplineGeometry2d :: Load (const char * filename) +{ + ifstream infile; + int nump, numseg, nelp, i, leftdom, rightdom; + double x, y; + int hi1, hi2, hi3; + double hd; + char reco[50], ch; + + infile.open (filename); + + infile >> reco; + infile >> elto0; + + infile >> nump; + for (i = 0; i < nump; i++) + { + infile >> x >> y >> hd; + geompoints.Append (GeomPoint2d(x, y, hd)); + } + + infile >> numseg; + + SplineSegment * spline = 0; + for (i = 0; i < numseg; i++) + { + infile >> leftdom >> rightdom; + + infile >> nelp; + switch (nelp) + { // type of spline segement + case 2: + { // a line + infile >> hi1 >> hi2; + spline = new LineSegment(geompoints[hi1-1], + geompoints[hi2-1]); + break; + } + case 3: + { // a rational spline + infile >> hi1 >> hi2 >> hi3; + spline = new SplineSegment3 (geompoints[hi1-1], + geompoints[hi2-1], + geompoints[hi3-1]); + break; + } + case 4: + { // an arc + infile >> hi1 >> hi2 >> hi3; + splines.Append (new CircleSegment (geompoints[hi1-1], + geompoints[hi2-1], + geompoints[hi3-1])); + break; + } + } + + infile >> spline->reffak; + spline -> leftdom = leftdom; + spline -> rightdom = rightdom; + splines.Append (spline); + + + + 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); + + splines.Last()->bc = int (flags.GetNumFlag ("bc", i+1)); + splines.Last()->copyfrom = int (flags.GetNumFlag ("copy", -1)); + } + + + Box<2> bbox; + GetBoundingBox (bbox); + // cout << "bbox = " << bbox << endl; +} + + + +void SplineGeometry2d :: +PartitionBoundary (double h, Mesh & mesh2d) +{ + for (int i = 0; i < splines.Size(); i++) + if (splines[i]->copyfrom == -1) + splines[i]->Partition(h, elto0, mesh2d, i+1); + else + CopyEdgeMesh (splines[i]->copyfrom, i+1, mesh2d); +} + + +void SplineGeometry2d :: CopyEdgeMesh (int from, int to, Mesh & mesh) +{ + int i, j, k; + + ARRAY<int> mappoints (mesh.GetNP()); + ARRAY<double> param (mesh.GetNP()); + mappoints = -1; + param = 0; + + Point3d pmin, pmax; + mesh.GetBox (pmin, pmax); + double diam2 = Dist2(pmin, pmax); + + 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.p1) = 1; + param.Elem(seg.p1) = seg.epgeominfo[0].dist; + + mappoints.Elem(seg.p2) = 1; + param.Elem(seg.p2) = seg.epgeominfo[1].dist; + } + } + + for (i = 1; i <= mappoints.Size(); i++) + { + if (mappoints.Get(i) != -1) + { + Point<2> newp = splines.Get(to)->GetPoint (param.Get(i)); + Point<3> newp3 (newp(0), newp(1), 0); + + int npi = -1; + + for (PointIndex pi = PointIndex::BASE; + pi < mesh.GetNP()+PointIndex::BASE; pi++) + if (Dist2 (mesh.Point(pi), newp3) < 1e-12 * diam2) + npi = pi; + + if (npi == -1) + { + npi = mesh.AddPoint (newp3); + } + + mappoints.Elem(i) = npi; + + mesh.GetIdentifications().Add (i, npi, to); + } + } + + // 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 = splines.Get(to)->bc; + nseg.p1 = mappoints.Get(seg.p1); + nseg.p2 = mappoints.Get(seg.p2); + nseg.domin = splines.Get(to)->leftdom; + nseg.domout = splines.Get(to)->rightdom; + + nseg.epgeominfo[0].edgenr = to; + nseg.epgeominfo[0].dist = param.Get(seg.p1); + nseg.epgeominfo[1].edgenr = to; + nseg.epgeominfo[1].dist = param.Get(seg.p2); + mesh.AddSegment (nseg); + } + } +} + + +void SplineGeometry2d :: +GetBoundingBox (Box<2> & box) const +{ + if (!splines.Size()) + { + box.Set (Point<2> (0,0)); + return; + } + + ARRAY<Point<2> > 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]); + } +} + +} diff --git a/Netgen/libsrc/geom2d/splinegeometry2.hpp b/Netgen/libsrc/geom2d/splinegeometry2.hpp new file mode 100644 index 0000000000..38de574b24 --- /dev/null +++ b/Netgen/libsrc/geom2d/splinegeometry2.hpp @@ -0,0 +1,43 @@ +#ifndef FILE_SPLINEGEOMETRY2 +#define FILE_SPLINEGEOMETRY2 + +/**************************************************************************/ +/* File: splinegeometry2.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 24. Jul. 96 */ +/**************************************************************************/ + + + +/// +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 SplineGeometry2d +{ + ARRAY<GeomPoint2d> geompoints; + ARRAY<SplineSegment*> splines; + double elto0; + +public: + void Load (const char * filename); + void PartitionBoundary (double h, Mesh & mesh2d); + + void CopyEdgeMesh (int from, int to, Mesh & mesh2d); + + const ARRAY<SplineSegment*> & GetSplines () const + { return splines; } + + void GetBoundingBox (Box<2> & box) const; +}; + + + +#endif diff --git a/Netgen/libsrc/gprim/Makefile b/Netgen/libsrc/gprim/Makefile new file mode 100644 index 0000000000..608e522844 --- /dev/null +++ b/Netgen/libsrc/gprim/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for geometric library +# +src = geom2d.cpp geom3d.cpp \ + geomtest3d.cpp adtree.cpp transform3d.cpp geomfuncs.cpp + +# reftrans.cpp rot3d.cpp +# +lib = gprim +libpath = libsrc/gprim +# +# +include ../makefile.inc +# diff --git a/Netgen/libsrc/gprim/adtree.cpp b/Netgen/libsrc/gprim/adtree.cpp new file mode 100644 index 0000000000..b3e3f13795 --- /dev/null +++ b/Netgen/libsrc/gprim/adtree.cpp @@ -0,0 +1,2292 @@ +#include <mystdlib.h> + + +#include <myadt.hpp> +// class DenseMatrix; +#include <gprim.hpp> + +namespace netgen +{ + + +/* ******************************* ADTree ******************************* */ + + +ADTreeNode :: ADTreeNode(int adim) +{ + pi = 0; + + 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; + ADTreeNode *next; + int dir; + int lr; + + float * bmin = new float [dim]; + float * bmax = new float [dim]; + + memcpy (bmin, cmin, dim * sizeof(float)); + memcpy (bmax, cmax, dim * sizeof(float)); + +#ifdef MARK + MARK (insertloop3) +#endif + + next = root; + dir = 0; + while (next) + { + node = next; + + if (!node->pi) + { + memcpy (node->data, p, dim * sizeof(float)); + node->pi = 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 == dim) + dir = 0; + } + +#ifdef MARK + MARK (insertend3) +#endif + + + 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) + 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 ADTree :: DeleteElement (int pi) +{ + ADTreeNode * node = ela.Get(pi); + + node->pi = 0; + + 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 0; + + 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) + return node->pi; + } + } + while (stackindex > 0); + + return 0; +} + + +void ADTree :: GetMatch (ARRAY <int> & matches) +{ + int nodenr; + + Reset(); + + while (nodenr = Next()) + 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 = 0; + + 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) +{ + ADTreeNode3 * ap; + return ball.Alloc(); +} + +void ADTreeNode3 :: operator delete (void * p) +{ + ball.Free (p); + // ::delete [] 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; + ADTreeNode3 *next; + int dir; + int lr; + + float bmin[3]; + float bmax[3]; + + memcpy (bmin, cmin, 3 * sizeof(float)); + memcpy (bmax, cmax, 3 * sizeof(float)); + +#ifdef MARK + // MARK (insertloop3) +#endif + + 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; + } + + 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; + } + +#ifdef MARK + // MARK (insertend3) +#endif + + + next = new ADTreeNode3; + memcpy (next->data, p, 3 * sizeof(float)); + next->pi = 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 ADTree3 :: DeleteElement (int pi) +{ + ADTreeNode3 * node = ela.Get(pi); + + node->pi = 0; + + 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, 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; + + 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); +} + + + + + + + + + +/* ******************************* 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)); + +#ifdef MARK + // MARK (insertloop3) +#endif + + // (*testout) << endl << "add point " << Point3d (p[0], p[1], p[2]) << endl; + + 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; + } + +#ifdef MARK + // MARK (insertend3) +#endif + + + 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)); + +#ifdef MARK + // MARK (insertloop3) +#endif + + 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; + } + +#ifdef MARK + // MARK (insertend3) +#endif + + + 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)); + +#ifdef MARK + // MARK (insertloop3) +#endif + + 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)); + +#ifdef MARK + // MARK (insertloop3) +#endif + + 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]); +} + + + + + + + + + + +/* ******************************* ADTree6 ******************************* */ + + +ADTreeNode6 :: ADTreeNode6() +{ + pi = 0; + + 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) +{ + 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; + ADTreeNode6 *next; + int dir; + int lr; + + float bmin[6]; + float bmax[6]; + + + memcpy (bmin, cmin, 6 * sizeof(float)); + memcpy (bmax, cmax, 6 * sizeof(float)); + +#ifdef MARK + MARK (insertloop6) +#endif + + next = root; + dir = 0; + 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; + } + + 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; + } + +#ifdef MARK + MARK (insertend6) +#endif + + + next = new ADTreeNode6; + memcpy (next->data, p, 6 * sizeof(float)); + next->pi = 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 ADTree6 :: DeleteElement (int pi) +{ + ADTreeNode6 * node = ela.Get(pi); + + node->pi = 0; + + 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); + ADTreeNode6 * node; + int dir, stacks; + + stack.SetSize (10000); + pis.SetSize(0); + + stack.Elem(1).node = root; + stack.Elem(1).dir = 0; + stacks = 1; + + while (stacks) + { + node = stack.Get(stacks).node; + dir = stack.Get(stacks).dir; + stacks--; + + if (node->pi) + { + +// int in = 1; +// for (i = 0; i < 3; i++) +// if (/* node->data[i] < bmin[i] || */ node->data[i] > bmax[i] || +// node->data[i+3] < bmin[i+3] /* || node->data[i+3] > bmax[i+3] */ ) +// { +// in = 0; +// break; +// } + +// if (in) +// pis.Append (node->pi); + + if (node->data[0] > bmax[0] || + node->data[1] > bmax[1] || + node->data[2] > bmax[2] || + node->data[3] < bmin[3] || + node->data[4] < bmin[4] || + node->data[5] < bmin[5]) + ; + else + pis.Append (node->pi); + } + + + int ndir = dir+1; + if (ndir == 6) + ndir = 0; + + if (node->left && bmin[dir] <= node->sep) + { + stacks++; + stack.Elem(stacks).node = node->left; + stack.Elem(stacks).dir = ndir; + } + if (node->right && bmax[dir] >= node->sep) + { + stacks++; + stack.Elem(stacks).node = node->right; + stack.Elem(stacks).dir = ndir; + } + } +} + +/* +void ADTree6 :: GetIntersecting (const float * bmin, + const float * bmax, + ARRAY<int> & pis) const +{ + static ARRAY<ADTreeNode6*> stack(10000); + static ARRAY<int> stackdir(10000); + ADTreeNode6 * node; + int dir, stacks; + + stack.SetSize (10000); + stackdir.SetSize(10000); + 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] > 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; + if (ndir == 6) + 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 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; +} + + + + + + + +/* ******************************* 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)); + +#ifdef MARK + // MARK (insertloop3) +#endif + + 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]); +} + + + + +/* ************************************* Point3dTree ********************** */ + + + +Point3dTree :: Point3dTree (const Point3d & pmin, const Point3d & pmax) +{ + float pmi[3], pma[3]; + for (int i = 0; i < 3; i++) + { + pmi[i] = pmin.X(i+1); + pma[i] = pmax.X(i+1); + } + tree = new ADTree3 (pmi, pma); +} + +Point3dTree :: ~Point3dTree () +{ + delete tree; +} + + + +void Point3dTree :: Insert (const Point3d & p, int pi) +{ + static float pd[3]; + pd[0] = p.X(); + pd[1] = p.Y(); + pd[2] = p.Z(); + tree->Insert (pd, pi); +} + +void Point3dTree :: GetIntersecting (const Point3d & pmin, const Point3d & pmax, + ARRAY<int> & pis) const +{ + float pmi[3], pma[3]; + for (int i = 0; i < 3; i++) + { + pmi[i] = pmin.X(i+1); + pma[i] = pmax.X(i+1); + } + tree->GetIntersecting (pmi, pma, pis); +} + + + + + + + + + + +Box3dTree :: Box3dTree (const Point3d & apmin, const Point3d & apmax) +{ + boxpmin = apmin; + boxpmax = apmax; + float tpmin[6], tpmax[6]; + for (int i = 0; i < 3; i++) + { + tpmin[i] = tpmin[i+3] = boxpmin.X(i+1); + tpmax[i] = tpmax[i+3] = boxpmax.X(i+1); + } + tree = new ADTree6 (tpmin, tpmax); +} + +Box3dTree :: ~Box3dTree () +{ + delete tree; +} + +void Box3dTree :: Insert (const Point3d & bmin, const Point3d & bmax, int pi) +{ + static float tp[6]; + + for (int i = 0; i < 3; i++) + { + tp[i] = bmin.X(i+1); + tp[i+3] = bmax.X(i+1); + } + + tree->Insert (tp, pi); +} + +void Box3dTree ::GetIntersecting (const Point3d & pmin, const Point3d & pmax, + ARRAY<int> & pis) const +{ + float tpmin[6]; + float tpmax[6]; + + for (int i = 0; i < 3; i++) + { + tpmin[i] = boxpmin.X(i+1); + tpmax[i] = pmax.X(i+1); + + tpmin[i+3] = pmin.X(i+1); + tpmax[i+3] = boxpmax.X(i+1); + } + + tree->GetIntersecting (tpmin, tpmax, pis); +} + +} diff --git a/Netgen/libsrc/gprim/adtree.hpp b/Netgen/libsrc/gprim/adtree.hpp new file mode 100644 index 0000000000..d28f873086 --- /dev/null +++ b/Netgen/libsrc/gprim/adtree.hpp @@ -0,0 +1,477 @@ +#ifndef FILE_ADTREE +#define FILE_ADTREE + +/* *************************************************************************/ +/* File: adtree.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 16. Feb. 98 */ +/* Redesigned by Wolfram Muehlhuber, May 1998 */ +/* *************************************************************************/ + + + +/** + Alternating Digital Tree + */ + +#include <mystdlib.h> +#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: + Point3dTree (const Point3d & pmin, const Point3d & pmax); + ~Point3dTree (); + void Insert (const Point3d & p, int pi); + void DeleteElement (int pi) + { tree->DeleteElement(pi); } + void GetIntersecting (const Point3d & pmin, const Point3d & pmax, + ARRAY<int> & pis) const; + const ADTree3 & Tree() const { return *tree; }; +}; + + + +class Box3dTree +{ + ADTree6 * tree; + Point3d boxpmin, boxpmax; +public: + Box3dTree (const Point3d & apmin, const Point3d & apmax); + ~Box3dTree (); + void Insert (const Point3d & bmin, const Point3d & bmax, int pi); + void DeleteElement (int pi) + { tree->DeleteElement(pi); } + void GetIntersecting (const Point3d & pmin, const Point3d & pmax, + ARRAY<int> & pis) const; + + const ADTree6 & Tree() const { return *tree; }; +}; +#endif diff --git a/Netgen/libsrc/gprim/geom2d.cpp b/Netgen/libsrc/gprim/geom2d.cpp new file mode 100644 index 0000000000..01463d0255 --- /dev/null +++ b/Netgen/libsrc/gprim/geom2d.cpp @@ -0,0 +1,485 @@ +#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/Netgen/libsrc/gprim/geom2d.hpp b/Netgen/libsrc/gprim/geom2d.hpp new file mode 100644 index 0000000000..48b5eda71d --- /dev/null +++ b/Netgen/libsrc/gprim/geom2d.hpp @@ -0,0 +1,870 @@ +#ifndef FILE_GEOM2D +#define FILE_GEOM2D + +/* *************************************************************************/ +/* File: geom2d.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 5. Aug. 95 */ +/* *************************************************************************/ + + + +/* 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); +double Angle (const Vec2d & v); +double FastAngle (const Vec2d & v); +double Angle (const Vec2d & v1, const Vec2d & v2); +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); +Point2d CrossPoint (const PLine2d & l1, const PLine2d & 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); + +/// +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 int 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; + } + + /// + 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 double Angle (const Vec2d & v); + /// + friend double FastAngle (const Vec2d & v); + /// + friend double Angle (const Vec2d & v1, const Vec2d & v2); + /// + friend 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 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/Netgen/libsrc/gprim/geom3d.cpp b/Netgen/libsrc/gprim/geom3d.cpp new file mode 100644 index 0000000000..b243e62c3a --- /dev/null +++ b/Netgen/libsrc/gprim/geom3d.cpp @@ -0,0 +1,640 @@ +#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]; + } +} + + +/* +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) +{ + 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/Netgen/libsrc/gprim/geom3d.hpp b/Netgen/libsrc/gprim/geom3d.hpp new file mode 100644 index 0000000000..fd60e6b26f --- /dev/null +++ b/Netgen/libsrc/gprim/geom3d.hpp @@ -0,0 +1,728 @@ +#ifndef FILE_GEOM3D +#define FILE_GEOM3D + +/* *************************************************************************/ +/* File: geom3d.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 5. Aug. 95 */ +/* *************************************************************************/ + + + + +extern 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); + +/// 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]; } + + /// + 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; + } + else + { + cerr << "Vec div by 0, v = " << (*this) << endl; + // MyError ("Vec3d::operator /=: Divisioin by zero"); + } + 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); + /// + 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/Netgen/libsrc/gprim/geomfuncs.cpp b/Netgen/libsrc/gprim/geomfuncs.cpp new file mode 100644 index 0000000000..b2ac83824a --- /dev/null +++ b/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/Netgen/libsrc/gprim/geomfuncs.hpp b/Netgen/libsrc/gprim/geomfuncs.hpp new file mode 100644 index 0000000000..b013261df8 --- /dev/null +++ b/Netgen/libsrc/gprim/geomfuncs.hpp @@ -0,0 +1,129 @@ +#ifndef FILE_GEOMFUNCS +#define FILE_GEOMFUNCS + +/* *************************************************************************/ +/* File: geomfuncs.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Jul. 02 */ +/* *************************************************************************/ + + +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; +} + + + +inline Vec<3> Cross (const Vec<3> & v1, const 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) ); +} + + +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); + + + +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/Netgen/libsrc/gprim/geomobjects.hpp b/Netgen/libsrc/gprim/geomobjects.hpp new file mode 100644 index 0000000000..9f6a8f025b --- /dev/null +++ b/Netgen/libsrc/gprim/geomobjects.hpp @@ -0,0 +1,333 @@ +#ifndef FILE_OBJECTS +#define FILE_OBJECTS + +/* *************************************************************************/ +/* File: geomobjects.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Jul. 02 */ +/* *************************************************************************/ + + + +template <int D> class Vec; +template <int D> class Point; + + +template <int D> +class Point +{ + +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); } + + + Point & operator= (const Point<D> & p2) + { + for (int i = 0; i < D; i++) x[i] = p2.x[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 +{ + +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); } + + + 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]; } + + 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/Netgen/libsrc/gprim/geomobjects2.hpp b/Netgen/libsrc/gprim/geomobjects2.hpp new file mode 100644 index 0000000000..014a38525a --- /dev/null +++ b/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/Netgen/libsrc/gprim/geomops.hpp b/Netgen/libsrc/gprim/geomops.hpp new file mode 100644 index 0000000000..0b783c076b --- /dev/null +++ b/Netgen/libsrc/gprim/geomops.hpp @@ -0,0 +1,374 @@ +#ifndef FILE_GEOMOPS +#define FILE_GEOMOPS + +/* *************************************************************************/ +/* File: geomops.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Jul. 02 */ +/* *************************************************************************/ + + +/* + +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<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/Netgen/libsrc/gprim/geomops2.hpp b/Netgen/libsrc/gprim/geomops2.hpp new file mode 100644 index 0000000000..c615da14ec --- /dev/null +++ b/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/Netgen/libsrc/gprim/geomtest3d.cpp b/Netgen/libsrc/gprim/geomtest3d.cpp new file mode 100644 index 0000000000..14d1d58bd1 --- /dev/null +++ b/Netgen/libsrc/gprim/geomtest3d.cpp @@ -0,0 +1,1223 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <gprim.hpp> + +namespace netgen +{ +int +IntersectTriangleLine (const Point3d ** tri, const Point3d ** 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 = 1; i <= 3; i++) + { + a.Elem(i, 1) = -vl.X(i); + a.Elem(i, 2) = vt1.X(i); + a.Elem(i, 3) = vt2.X(i); + rs.Elem(i) = vrs.X(i); + } + + 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.Get(1) >= -eps && lami.Get(1) <= 1+eps && + lami.Get(2) >= -eps && lami.Get(3) >= -eps && + lami.Get(2) + lami.Get(3) <= 1+eps) && ! + (lami.Get(1) >= eps && lami.Get(1) <= 1-eps && + lami.Get(2) >= eps && lami.Get(3) >= eps && + lami.Get(2) + lami.Get(3) <= 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.Get(1) >= 0 && lami.Get(1) <= 1 && + lami.Get(2) >= 0 && lami.Get(3) >= 0 && lami.Get(2) + lami.Get(3) <= 1) + { + + return 1; + } + + return 0; +} + + + + + +int IntersectTetTriangle (const Point3d ** tet, const Point3d ** 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; + +#ifdef MARK + MARK (inttettri1); +#endif + + double eps2 = eps * eps; + int loctripi[3], cnt = 0; + int loctetpi[4]; + + 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; + +#ifdef MARK + MARK (inttettri2); +#endif + + + // (*testout) << "tet-trig inters, cnt = " << cnt << endl; + + // cnt .. number of common points + switch (cnt) + { + case 0: + { +#ifdef MARK + MARK (inttettric0); +#endif + + 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 Point3d * 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: + { +#ifdef MARK + MARK (inttettric1); +#endif + + 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: + { +#ifdef MARK + MARK (inttettric2); +#endif + + // 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: + { +#ifdef MARK + MARK (inttettric3); +#endif + + // common face + return 0; + } + } + + (*testout) << "hit, cnt = " << cnt << endl; + return 1; +} + + + + + +int IntersectTetTriangleRef (const Point3d ** tri, const int * tripi) +{ + int i, j; + double eps = 1e-8; + double eps2 = eps * eps; + + static Point3d rtetp1(0, 0, 0); + static Point3d rtetp2(1, 0, 0); + static Point3d rtetp3(0, 1, 0); + static Point3d rtetp4(0, 0, 1); + + static const Point3d * 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; + +#ifdef MARK + MARK (inttettriref2); +#endif + + + switch (cnt) + { + case 0: + { +#ifdef MARK + MARK (inttettric0ref); +#endif + + Vec3d no, n; + // int inpi[3]; + int pside[3][4]; + + for (j = 0; j < 3; j++) + { + pside[j][0] = (*tri[j]).X() > -eps; + pside[j][1] = (*tri[j]).Y() > -eps; + pside[j][2] = (*tri[j]).Z() > -eps; + pside[j][3] = (*tri[j]).X() + (*tri[j]).Y() + (*tri[j]).Z() < 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 Point3d * 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: + { +#ifdef MARK + MARK (inttettric1ref); +#endif + + 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: + { +#ifdef MARK + MARK (inttettric2ref); +#endif + + // 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: + { +#ifdef MARK + MARK (inttettric3ref); +#endif + + // common face + return 0; + } + } + + (*testout) << "hit, cnt = " << cnt << endl; + return 1; +} + + + + + + + + + + + +int IntersectTriangleTriangle (const Point3d ** tri1, const Point3d ** 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 Point3d * 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 Point3d ** pts, Point3d & c) +{ + /* + static DenseMatrix a(3), inva(3); + static Vector rs(3), sol(3); + int i; + double h = Dist(*pts[0], *pts[1]); + + for (i = 1; i <= 3; i++) + { + const Point3d & p1 = *pts[0]; + const Point3d & p2 = *pts[i]; + Vec3d v(p1, p2); + a.Elem(i,1) = v.X(); + a.Elem(i,2) = v.Y(); + a.Elem(i,3) = v.Z(); + + rs.Elem(i) = 0.5 * (v * v); + } + + if (fabs (a.Det()) <= 1e-12 * h * h * h) + { + (*testout) << "CalcSphereCenter: degenerated" << endl; + return 1; + } + + CalcInverse (a, inva); + inva.Mult (rs, sol); + + for (i = 1; i <= 3; i++) + c.X(i) = pts[0]->X(i) + sol.Elem(i); + */ + + 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.Elem(1) = v1 * v1; + rs.Elem(2) = v2 * v2; + + a.Elem(1,1) = 2 * rs.Get(1); + a.Elem(1,2) = a.Elem(2,1) = 2 * (v1 * v2); + a.Elem(2,2) = 2 * rs.Get(2); + + 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.Get(1); + v2 *= sol.Get(2); + + 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/Netgen/libsrc/gprim/geomtest3d.hpp b/Netgen/libsrc/gprim/geomtest3d.hpp new file mode 100644 index 0000000000..f801b8cdef --- /dev/null +++ b/Netgen/libsrc/gprim/geomtest3d.hpp @@ -0,0 +1,80 @@ +#ifndef FILE_GEOMTEST3D +#define FILE_GEOMTEST3D + +/* *************************************************************************/ +/* File: geomtest3d.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 13. Feb. 98 */ +/* *************************************************************************/ + + + +extern int +IntersectTriangleLine (const Point3d ** tri, const Point3d ** 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 Point3d ** tet, const Point3d ** 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 Point3d ** tri1, const Point3d ** 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 Point3d ** pts, Point3d & 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); + + +extern double MinDistLP2 (const Point2d & lp1, const Point2d & lp2, const Point2d & p); + +extern double MinDistLP2 (const Point3d & lp1, const Point3d & lp2, const Point3d & p); + +extern double MinDistTP2 (const Point3d & tp1, const Point3d & tp2, + const Point3d & tp3, const Point3d & p); + +extern double MinDistLL2 (const Point3d & l1p1, const Point3d & l1p2, + const Point3d & l2p1, const Point3d & l2p2); + + +#endif diff --git a/Netgen/libsrc/gprim/gprim.hpp b/Netgen/libsrc/gprim/gprim.hpp new file mode 100644 index 0000000000..0f57ebac86 --- /dev/null +++ b/Netgen/libsrc/gprim/gprim.hpp @@ -0,0 +1,26 @@ +#ifndef FILE_GPRIM +#define FILE_GPRIM + +/* *************************************************************************/ +/* File: gprim.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 14. Aug. 97 */ +/* *************************************************************************/ + + +namespace netgen +{ +#include "geomobjects.hpp" +#include "geomops.hpp" +#include "geomfuncs.hpp" + +#include "geom2d.hpp" +#include "geom3d.hpp" +#include "geomtest3d.hpp" +// #include "rot3d.hpp" +#include "transform3d.hpp" +// #include "reftrans.hpp" +#include "adtree.hpp" +} + +#endif diff --git a/Netgen/libsrc/gprim/testgeom.cpp b/Netgen/libsrc/gprim/testgeom.cpp new file mode 100644 index 0000000000..8413f0f2b5 --- /dev/null +++ b/Netgen/libsrc/gprim/testgeom.cpp @@ -0,0 +1,20 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <gprim.hpp> + + +Vec<2> func1 (const Point<2> & a, const Point<2> & b) +{ + return a-b; +} + +void func2 (Point<3> & a, Vec<3> & v) +{ + a += 3.4 * v; +} + +void func3 (const Mat<2,2> & m, const Vec<2> & vc, Vec<2> & res) +{ + res += Trans (m) * vc; +} diff --git a/Netgen/libsrc/gprim/transform3d.cpp b/Netgen/libsrc/gprim/transform3d.cpp new file mode 100644 index 0000000000..40ef4e3b2a --- /dev/null +++ b/Netgen/libsrc/gprim/transform3d.cpp @@ -0,0 +1,172 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <gprim.hpp> +#include <linalg.hpp> + +namespace netgen +{ + +Transformation3d :: Transformation3d () +{ + int i, j; + for (i = 0; i < 3; i++) + { + offset[i] = 0; + for (j = 0; j < 3; j++) + lin[i][j] = 0; + } +} + +Transformation3d :: Transformation3d (const Vec3d & translate) +{ + int i, j; + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + lin[i][j] = 0; + for (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); + + // (*testout) << "Rotation - Transformation:" << (*this) << endl; +} + + + + +Transformation3d :: Transformation3d (const Point3d ** pp) +{ + int i, j; + for (i = 1; i <= 3; i++) + { + offset[i-1] = (*pp[0]).X(i); + for (j = 1; j <= 3; j++) + lin[i-1][j-1] = (*pp[j]).X(i) - (*pp[0]).X(i); + } +} + +Transformation3d :: Transformation3d (const Point3d pp[]) +{ + int i, j; + for (i = 1; i <= 3; i++) + { + offset[i-1] = pp[0].X(i); + for (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); + int i, j; + + for (i = 1; i <= 3; i++) + { + b.Elem(i) = offset[i-1]; + for (j = 1; j <= 3; j++) + a.Elem(i, j) = lin[i-1][j-1]; + } + + ::netgen::CalcInverse (a, inva); + inva.Mult (b, sol); + + for (i = 1; i <= 3; i++) + { + inv.offset[i-1] = -sol.Get(i); + for (j = 1; j <= 3; j++) + inv.lin[i-1][j-1] = inva.Elem(i, j); + } +} + + +void Transformation3d:: +Combine (const Transformation3d & ta, const Transformation3d & tb) +{ + int i, j, k; + + // o = o_a+ m_a o_b + // m = m_a m_b + + for (i = 0; i <= 2; i++) + { + offset[i] = ta.offset[i]; + for (j = 0; j <= 2; j++) + offset[i] += ta.lin[i][j] * tb.offset[j]; + } + + for (i = 0; i <= 2; i++) + for (j = 0; j <= 2; j++) + { + lin[i][j] = 0; + for (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) +{ + int i, j; + ost << "offset = "; + for (i = 0; i <= 2; i++) + ost << trans.offset[i] << " "; + ost << endl << "linear = " << endl; + for (i = 0; i <= 2; i++) + { + for (j = 0; j <= 2; j++) + ost << trans.lin[i][j] << " "; + ost << endl; + } + return ost; +} +} diff --git a/Netgen/libsrc/gprim/transform3d.hpp b/Netgen/libsrc/gprim/transform3d.hpp new file mode 100644 index 0000000000..9eccc5a7f9 --- /dev/null +++ b/Netgen/libsrc/gprim/transform3d.hpp @@ -0,0 +1,131 @@ +#ifndef FILE_TRANSFORM3D +#define FILE_TRANSFORM3D + +/* *************************************************************************/ +/* File: transform3d.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 22. Mar. 98 */ +/* *************************************************************************/ + +/* + Affine - Linear mapping in 3D space + */ + +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); + } + } + /// 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) + { + ; + } + + /// + 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); + + /// + void Transform (const Point<D> & from, Point<D> & to) const + { + to = Point<D> (v + m * Vec<D>(from)); + } + + /// 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/Netgen/libsrc/include/csg.hpp b/Netgen/libsrc/include/csg.hpp new file mode 100644 index 0000000000..ffd45ef0bf --- /dev/null +++ b/Netgen/libsrc/include/csg.hpp @@ -0,0 +1 @@ +#include "../csg/csg.hpp" diff --git a/Netgen/libsrc/include/geometry2d.hpp b/Netgen/libsrc/include/geometry2d.hpp new file mode 100644 index 0000000000..bf0965c228 --- /dev/null +++ b/Netgen/libsrc/include/geometry2d.hpp @@ -0,0 +1 @@ +#include "../geom2d/geometry2d.hpp" diff --git a/Netgen/libsrc/include/gprim.hpp b/Netgen/libsrc/include/gprim.hpp new file mode 100644 index 0000000000..1e827aaf8c --- /dev/null +++ b/Netgen/libsrc/include/gprim.hpp @@ -0,0 +1 @@ +#include "../gprim/gprim.hpp" diff --git a/Netgen/libsrc/include/incvis.hpp b/Netgen/libsrc/include/incvis.hpp new file mode 100644 index 0000000000..a38e918698 --- /dev/null +++ b/Netgen/libsrc/include/incvis.hpp @@ -0,0 +1,33 @@ +// libraries for User interface: + +/* +#include <tcl8.3.h> +#include <tk8.3.h> + +#include <GL/gl.h> +#include <GL/glu.h> +#include "../togl/togl.h" + +#include <tix8.1.h> +*/ + + +#include <tcl.h> +#include <tk.h> + + +#if TK_MAJOR_VERSION==8 && TK_MINOR_VERSION==4 +#define tcl_const const +#else +#define tcl_const +#endif + + +#include <GL/gl.h> +#include <GL/glu.h> +#include "../../togl/togl.h" + + + +// Just the init-call +// #include <tix.h> diff --git a/Netgen/libsrc/include/linalg.hpp b/Netgen/libsrc/include/linalg.hpp new file mode 100644 index 0000000000..e96bd036c3 --- /dev/null +++ b/Netgen/libsrc/include/linalg.hpp @@ -0,0 +1 @@ +#include "../linalg/linalg.hpp" diff --git a/Netgen/libsrc/include/meshing.hpp b/Netgen/libsrc/include/meshing.hpp new file mode 100644 index 0000000000..e41a88f9f2 --- /dev/null +++ b/Netgen/libsrc/include/meshing.hpp @@ -0,0 +1 @@ +#include <../meshing/meshing.hpp> diff --git a/Netgen/libsrc/include/myadt.hpp b/Netgen/libsrc/include/myadt.hpp new file mode 100644 index 0000000000..d36bef05c1 --- /dev/null +++ b/Netgen/libsrc/include/myadt.hpp @@ -0,0 +1 @@ +#include <../general/myadt.hpp> diff --git a/Netgen/libsrc/include/mydefs.hpp b/Netgen/libsrc/include/mydefs.hpp new file mode 100644 index 0000000000..c34ce56a8e --- /dev/null +++ b/Netgen/libsrc/include/mydefs.hpp @@ -0,0 +1,29 @@ +#ifndef FILE_MYDEFS +#define FILE_MYDEFS + +/**************************************************************************/ +/* File: mydefs.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 10. Mar. 98 */ +/**************************************************************************/ + +/* + defines for graphics, testmodes, ... +*/ + + +// #define DEBUG + + +#define noDEMOVERSION +#define noDEVELOP +#define noSTEP +#define noSOLIDGEOM + +#define noDEMOAPP +#define noMODELLER + +#define noSTAT_STREAM +#define noLOG_STREAM + +#endif diff --git a/Netgen/libsrc/include/occgeom.hpp b/Netgen/libsrc/include/occgeom.hpp new file mode 100644 index 0000000000..af258e0df0 --- /dev/null +++ b/Netgen/libsrc/include/occgeom.hpp @@ -0,0 +1 @@ +#include "../occ/occgeom.hpp" diff --git a/Netgen/libsrc/include/opti.hpp b/Netgen/libsrc/include/opti.hpp new file mode 100644 index 0000000000..6b8a0b61c8 --- /dev/null +++ b/Netgen/libsrc/include/opti.hpp @@ -0,0 +1 @@ +#include "../opti/opti.hpp" diff --git a/Netgen/libsrc/include/stepgeom.hpp b/Netgen/libsrc/include/stepgeom.hpp new file mode 100644 index 0000000000..d2c5c5e41e --- /dev/null +++ b/Netgen/libsrc/include/stepgeom.hpp @@ -0,0 +1,10 @@ +#include "../stepgeom/geomanif.hh" +#include "../stepgeom/geopac2d.hh" +#include "../stepgeom/geopac3d.hh" +#include "../stepgeom/geosplinesurf.hh" +#include "../stepgeom/algprim.hh" +#include "../stepgeom/scenery.hh" +#include "../stepgeom/brep.hh" +#include "../stepgeom/adtcrit.hh" +#include "../stepgeom/STEPgeom.hh" +#include "../stepgeom/visapprox.hh" diff --git a/Netgen/libsrc/include/stepreader.hpp b/Netgen/libsrc/include/stepreader.hpp new file mode 100644 index 0000000000..0214d58d9d --- /dev/null +++ b/Netgen/libsrc/include/stepreader.hpp @@ -0,0 +1 @@ +#include "../stepgeom/STEPread.hh" diff --git a/Netgen/libsrc/include/stlgeom.hpp b/Netgen/libsrc/include/stlgeom.hpp new file mode 100644 index 0000000000..f1eea264e1 --- /dev/null +++ b/Netgen/libsrc/include/stlgeom.hpp @@ -0,0 +1 @@ +#include <../stlgeom/stlgeom.hpp> diff --git a/Netgen/libsrc/include/visual.hpp b/Netgen/libsrc/include/visual.hpp new file mode 100644 index 0000000000..f026f5a458 --- /dev/null +++ b/Netgen/libsrc/include/visual.hpp @@ -0,0 +1 @@ +#include "../visualization/visual.hpp" diff --git a/Netgen/libsrc/interface/Makefile b/Netgen/libsrc/interface/Makefile new file mode 100644 index 0000000000..98d943a028 --- /dev/null +++ b/Netgen/libsrc/interface/Makefile @@ -0,0 +1,7 @@ +src = nginterface.cpp writeuser.cpp writediffpack.cpp writeabaqus.cpp writefluent.cpp writepermas.cpp writetochnog.cpp writetecplot.cpp wuchemnitz.cpp writetochnog.cpp writefeap.cpp readuser.cpp importsolution.cpp +# +lib = nginterface +libpath = libsrc/interface +# +include ../makefile.inc +# diff --git a/Netgen/libsrc/interface/importsolution.cpp b/Netgen/libsrc/interface/importsolution.cpp new file mode 100644 index 0000000000..3973d3927e --- /dev/null +++ b/Netgen/libsrc/interface/importsolution.cpp @@ -0,0 +1,121 @@ +// +// Read solution file +// + + +#include <mystdlib.h> + + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +#include "nginterface.h" + +namespace netgen +{ +#include "writeuser.hpp" + + +void ImportSolution (const char * filename) +{ + ifstream inf (filename); + char buf[100], name[1000]; + int i, j, 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; + if (strcmp (type, "element") == 0) + soldata.soltype = NG_SOLUTION_ELEMENT; + if (strcmp (type, "surfaceelement") == 0) + soldata.soltype = NG_SOLUTION_SURFACE_ELEMENT; + 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/Netgen/libsrc/interface/nginterface.cpp b/Netgen/libsrc/interface/nginterface.cpp new file mode 100644 index 0000000000..5510f28a27 --- /dev/null +++ b/Netgen/libsrc/interface/nginterface.cpp @@ -0,0 +1,1301 @@ +#include <mystdlib.h> + + +#include <meshing.hpp> +#include <csg.hpp> +#include <geometry2d.hpp> +#include <stlgeom.hpp> + +#include <visual.hpp> + +#include "nginterface.h" +// #include <FlexLexer.h> + + + + +namespace netgen +{ + extern AutoPtr<Mesh> mesh; + extern VisualSceneMesh vsmesh; + extern Tcl_Interp * tcl_interp; + + extern SplineGeometry2d * geometry2d; + extern CSGeometry * parsegeom; + extern CSGeometry * geometry; + extern STLGeometry * stlgeometry; + + extern VisualSceneSolution vssolution; + extern CSGeometry * ParseCSG (istream & istr); +} + + +using namespace netgen; + +/* + extern void * operator new (size_t s); + extern void * operator new [] (size_t s); + extern void operator delete (void * p); + extern void operator delete [] (void * p); +*/ + +// extern FlexLexer * lexer; + + + +void Ng_LoadGeometry (char * filename) +{ + ifstream infile (filename); + + if (geometry) + delete geometry; + + if (strcmp (&filename[strlen(filename)-3], "geo") == 0) + { + /* + geometry = new CSGeometry(filename); + + parsegeom = geometry; + + lexer = new yyFlexLexer (&infile); + + extern int yyparse (); + yyparse (); + delete lexer; + */ + + geometry = netgen::ParseCSG (infile); + + if (!geometry) + throw NgException ("input file not found"); + + geometry -> FindIdenticSurfaces(1e-6); + Box<3> box (geometry->BoundingBox()); + + geometry->CalcTriangleApproximation (box, 0.01, 10); + } + else + { + geometry = new CSGeometry(""); + + if (strcmp (&filename[strlen(filename)-4], "in2d") == 0) + { + + if (geometry2d) + delete geometry2d; + geometry2d = new SplineGeometry2d(); + geometry2d -> Load (filename); + } + + else + { + cerr << "Unknown geometry extension!!" << endl; + } + } +} + + +void Ng_LoadMesh (char * filename) +{ + mesh.Reset (new Mesh()); + mesh->Load (filename); +} + + + +int Ng_GetDimension () +{ + return mesh->GetDimension(); +} + +int Ng_GetNP () +{ + return mesh->GetNP(); +} + +int Ng_GetNV () +{ + return mesh->GetNV(); +} + +int Ng_GetNE () +{ + if (mesh->GetDimension() == 3) + return mesh->GetNE(); + else + return mesh->GetNSE(); +} + +int Ng_GetNSE () +{ + if (mesh->GetDimension() == 3) + return mesh->GetNSE(); + else + return mesh->GetNSeg(); +} + +void Ng_GetPoint (int pi, double * p) +{ + 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: + 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: + { + 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 + { + int i; + 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; + } +} + +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; + } + return 0; +} + +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.pmid) + { + epi[0] = seg.p1; + epi[1] = seg.p2; + + if (np) *np = 2; + return NG_SEGM; + } + else + { + epi[0] = seg.p1; + epi[1] = seg.p2; + epi[2] = seg.pmid; + + 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; +} + + +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(); + if (geometry) + { + geometry->GetSurface (surfi) -> GetNormalVector(p, n); + nv[0] = n(0); + nv[1] = n(1); + nv[2] = n(2); + } + } +} + + +int Ng_FindElementOfPoint (double * p, double * lami) +{ + if (mesh->GetDimension() == 3) + { + Point3d p3d(p[0], p[1], p[2]); + int ind = + mesh->GetElementOfPoint(p3d, lami); + return ind; + } + else + { + double lam3[3]; + Point3d p2d(p[0], p[1], 0); + int ind = + mesh->GetElementOfPoint(p2d, lam3); + lami[0] = lam3[0]; + lami[1] = lam3[1]; + return ind; + } +} + + + +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); + + // still 1-based arrays + 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]); + // (*testout) << "elnr = " << ei << ", eltrans, xl = " << xl << endl; + Point<3> xg; + Mat<3,3> dx; + + mesh->GetCurvedElements().CalcElementTransformation (xl, ei-1, xg, dx); + + // 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); + } + } + } +} + + +void Ng_GetSurfaceElementTransformation (int sei, const double * xi, + double * x, double * dxdxi) +{ + if (mesh->GetDimension() == 2) + { + Point<3> xg; + Vec<3> dx; + + // still 1-based arrays + 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; + + // still 1-based arrays + 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); + } + } + } +} + + + + +void Ng_SetRefinementFlag (int ei, int flag) +{ + if (mesh->GetDimension() == 3) + mesh->VolumeElement(ei).SetRefinementFlag (flag != 0); + else + mesh->SurfaceElement(ei).SetRefinementFlag (flag != 0); +} + +void Ng_SetSurfaceRefinementFlag (int ei, int flag) +{ + if (mesh->GetDimension() == 3) + mesh->SurfaceElement(ei).SetRefinementFlag (flag != 0); +} + + +void Ng_Refine (NG_REFINEMENT_TYPE reftype) +{ + BisectionOptions biopt; + biopt.usemarkedelements = 1; + biopt.refine_hp = 0; + if (reftype == NG_REFINE_P || reftype == NG_REFINE_HP) + biopt.refine_hp = 1; + + if (geometry && mesh->GetDimension() == 3) + { + RefinementSurfaces ref (*geometry); + ref.Bisect (*mesh, biopt); + } + else if (stlgeometry) + { + RefinementSTLGeometry ref (*stlgeometry); + ref.Bisect (*mesh, biopt); + } + else if (geometry2d) + { + Refinement2d ref (*geometry2d); + ref.Bisect (*mesh, biopt); + } + else + { + cout << "No geometry available" << endl; + Refinement ref; + ref.Bisect (*mesh, biopt); + } + + mesh -> UpdateTopology(); +} + +void Ng_SecondOrder () +{ + 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 + { + cout << "no geom" << endl; + Refinement ref; + ref.MakeSecondOrder (*mesh); + } + + mesh -> UpdateTopology(); +} + +void Ng_HPRefinement (int levels) +{ + HPRefinement (*mesh, levels); +} + + +void Ng_HighOrder (int order) +{ + Refinement * ref; + + if (stlgeometry) + ref = new RefinementSTLGeometry (*stlgeometry); + 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 (ref, order); + + 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; +} + + +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_GetElementOrder (int enr) +{ + if (mesh->GetDimension() == 3) + return mesh->VolumeElement(enr).GetOrder(); + else + return mesh->SurfaceElement(enr).GetOrder(); +} + + + +int Ng_GetNLevels () +{ + return mesh->mglevels; +} + + +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); +} + + + + + + +void Ng_InitSolutionData (Ng_SolutionData * soldata) +{ + soldata -> name = NULL; + soldata -> data = NULL; + soldata -> components = 1; + soldata -> dist = 1; + soldata -> order = 1; + soldata -> iscomplex = 0; + soldata -> draw_surface = 1; + soldata -> draw_volume = 1; + soldata -> soltype = NG_SOLUTION_NODAL; + soldata -> solclass = 0; +} + +void Ng_SetSolutionData (Ng_SolutionData * soldata) +{ + // vssolution.ClearSolutionData (); + VisualSceneSolution::SolData * vss = new VisualSceneSolution::SolData; + + // cout << "Add solution " << soldata->name << ", type = " << soldata->soltype << endl; + + vss->name = new char[strlen (soldata->name)+1]; + strcpy (vss->name, soldata->name); + + vss->data = soldata->data; + vss->components = soldata->components; + vss->dist = soldata->dist; + vss->order = soldata->order; + vss->iscomplex = bool(soldata->iscomplex); + vss->draw_surface = soldata->draw_surface; + vss->draw_volume = soldata->draw_volume; + vss->soltype = VisualSceneSolution::SolType (soldata->soltype); + vss->solclass = soldata->solclass; + vssolution.AddSolutionData (vss); +} + + +void Ng_Redraw () +{ + vssolution.UpdateSolutionTimeStamp(); + Render(); +} + + +void Ng_SetVisualizationParameter (const char * name, const char * value) +{ + char buf[100]; + sprintf (buf, "visoptions.%s", name); + cout << "name = " << name << ", value = " << value << endl; + cout << "set tcl-variable " << buf << " to " << value << endl; + Tcl_SetVar (tcl_interp, buf, const_cast<char*> (value), 0); + Tcl_Eval (tcl_interp, "Ng_Vis_Set parameters;"); +} + + + + +int firsttime = 1; +int animcnt = 0; +void PlayAnimFile(const char* name, int speed, int maxcnt) +{ + //extern Mesh * mesh; + + /* + if (mesh.Ptr()) mesh->DeleteMesh(); + if (!mesh.Ptr()) mesh = new Mesh(); + */ + mesh.Reset (new Mesh()); + + int ne, np, i, ti; + + char str[80]; + char str2[80]; + + //int tend = 5000; + // for (ti = 1; ti <= tend; ti++) + //{ + int rti = (animcnt%(maxcnt-1)) + 1; + animcnt+=speed; + + sprintf(str2,"%05i.sol",rti); + strcpy(str,"mbssol/"); + strcat(str,name); + strcat(str,str2); + + cout << "read file '" << str << "'" << endl; + + ifstream infile(str); + infile >> ne; + for (i = 1; i <= ne; i++) + { + int j; + Element2d tri(3); + tri.SetIndex(1); //faceind + + for (j = 1; j <= 3; j++) + infile >> tri.PNum(j); + + infile >> np; + for (i = 1; i <= np; i++) + { + Point3d p; + infile >> p.X() >> p.Y() >> p.Z(); + if (firsttime) + mesh->AddPoint (p); + else + mesh->Point(i)=p; + } + + //firsttime = 0; + Ng_Redraw(); + } +} + + +int Ng_GetNPeriodicVertices () +{ + ARRAY<INDEX_2> apairs; + mesh->GetIdentifications().GetPairs (0, apairs); + return apairs.Size(); +} + + +// pairs should be an integer array of 2*npairs +void Ng_GetPeriodicVertices (int * pairs) +{ + ARRAY<INDEX_2> apairs; + mesh->GetIdentifications().GetPairs (0, apairs); + for (int i = 0; i < apairs.Size(); i++) + { + pairs[2*i] = apairs[i].I1(); + pairs[2*i+1] = apairs[i].I2(); + } + + /*<<<<<< nginterface.cpp + infile >> np; + for (i = 1; i <= np; i++) + { + Point3d p; + infile >> p.X() >> p.Y() >> p.Z(); + if (firsttime) + mesh->AddPoint (p); + else + mesh->Point(i)=p; + } + + //firsttime = 0; + Ng_Redraw(); + //} +} + + +int Ng_GetNPeriodicVertices () +{ + ARRAY<INDEX_2> apairs; + mesh->GetIdentifications().GetPairs (0, apairs); + return apairs.Size(); +} + + +// pairs should be an integer array of 2*npairs +void Ng_GetPeriodicVertices (int * pairs) +{ + ARRAY<INDEX_2> apairs; + mesh->GetIdentifications().GetPairs (0, apairs); + for (int i = 0; i < apairs.Size(); i++) + { + pairs[2*i] = apairs[i].I1(); + pairs[2*i+1] = apairs[i].I2(); + } +======= + if (firsttime) + mesh->AddSurfaceElement (tri); + } + + infile >> np; + for (i = 1; i <= np; i++) + { + Point3d p; + infile >> p.X() >> p.Y() >> p.Z(); + if (firsttime) + mesh->AddPoint (p); + else + mesh->Point(i)=p; + } + + //firsttime = 0; + Ng_Redraw(); +>>>>>>> 1.9 +*/ +} + + diff --git a/Netgen/libsrc/interface/nglib.cpp b/Netgen/libsrc/interface/nglib.cpp new file mode 100644 index 0000000000..d309cd7189 --- /dev/null +++ b/Netgen/libsrc/interface/nglib.cpp @@ -0,0 +1,538 @@ +/**************************************************************************/ +/* File: nglib.cc */ +/* Author: Joachim Schoeberl */ +/* Date: 7. May. 2000 */ +/**************************************************************************/ + +/* + + Interface to the netgen meshing kernel + +*/ + + +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> +#include <stlgeom.hpp> +#include <geometry2d.hpp> +#include <meshing.hpp> + +// #include <FlexLexer.h> + +#include "nglib.h" + +using namespace netgen; + +// constants and types: + +// initialize, deconstruct Netgen library: +void Ng_Init () +{ + mycout = &cout; + myerr = &cerr; + testout = new ofstream ("test.out"); +} + +void Ng_Exit () +{ + ; +} + + + +Ng_Mesh * Ng_NewMesh () +{ + Mesh * mesh = new Mesh; + mesh->AddFaceDescriptor (FaceDescriptor (1, 1, 0, 1)); + return (Ng_Mesh*)(void*)mesh; +} + +void Ng_DeleteMesh (Ng_Mesh * mesh) +{ + delete (Mesh*)mesh; +} + + +// feeds points, surface elements and volume elements to the mesh +void Ng_AddPoint (Ng_Mesh * mesh, double * x) +{ + Mesh * m = (Mesh*)mesh; + m->AddPoint (Point3d (x[0], x[1], x[2])); +} + +void Ng_AddSurfaceElement (Ng_Mesh * mesh, Ng_Surface_Element_Type et, + int * pi) +{ + Mesh * m = (Mesh*)mesh; + Element2d el (3); + el.SetIndex (1); + el.PNum(1) = pi[0]; + el.PNum(2) = pi[1]; + el.PNum(3) = pi[2]; + m->AddSurfaceElement (el); +} + +void Ng_AddVolumeElement (Ng_Mesh * mesh, Ng_Volume_Element_Type et, + int * pi) +{ + Mesh * m = (Mesh*)mesh; + Element el (4); + el.SetIndex (1); + el.PNum(1) = pi[0]; + el.PNum(2) = pi[1]; + el.PNum(3) = pi[2]; + el.PNum(4) = pi[3]; + m->AddVolumeElement (el); +} + +// ask for number of points, surface and volume elements +int Ng_GetNP (Ng_Mesh * mesh) +{ + return ((Mesh*)mesh) -> GetNP(); +} + +int Ng_GetNSE (Ng_Mesh * mesh) +{ + return ((Mesh*)mesh) -> GetNSE(); +} + +int Ng_GetNE (Ng_Mesh * mesh) +{ + return ((Mesh*)mesh) -> GetNE(); +} + + +// return point coordinates +void Ng_GetPoint (Ng_Mesh * mesh, int num, double * x) +{ + const Point3d & p = ((Mesh*)mesh)->Point(num); + x[0] = p.X(); + x[1] = p.Y(); + x[2] = p.Z(); +} + +// return surface and volume element in pi +Ng_Surface_Element_Type +Ng_GetSurfaceElement (Ng_Mesh * mesh, int num, int * pi) +{ + const Element2d & el = ((Mesh*)mesh)->SurfaceElement(num); + for (int i = 1; i <= el.GetNP(); i++) + pi[i-1] = el.PNum(i); + Ng_Surface_Element_Type et; + switch (el.GetNP()) + { + case 3: et = NG_TRIG; break; + case 4: et = NG_QUAD; break; + case 6: et = NG_TRIG6; break; + } + return et; +} + +Ng_Volume_Element_Type +Ng_GetVolumeElement (Ng_Mesh * mesh, int num, int * pi) +{ + const Element & el = ((Mesh*)mesh)->VolumeElement(num); + for (int i = 1; i <= el.GetNP(); i++) + pi[i-1] = el.PNum(i); + Ng_Volume_Element_Type et; + switch (el.GetNP()) + { + case 4: et = NG_TET; break; + case 5: et = NG_PYRAMID; break; + case 6: et = NG_PRISM; break; + case 10: et = NG_TET10; break; + } + return et; +} + + + +// generates volume mesh from surface mesh +Ng_Result Ng_GenerateVolumeMesh (Ng_Mesh * mesh, Ng_Meshing_Parameters * mp) +{ + Mesh * m = (Mesh*)mesh; + + + MeshingParameters mparam; + mparam.maxh = mp->maxh; + mparam.meshsizefilename = mp->meshsize_filename; + + m->CalcLocalH(); + + MeshVolume (mparam, *m); + RemoveIllegalElements (*m); + OptimizeVolume (mparam, *m, NULL); + + return NG_OK; +} + + + +// 2D Meshing Functions: + + + +void Ng_AddPoint_2D (Ng_Mesh * mesh, double * x) +{ + Mesh * m = (Mesh*)mesh; + + m->AddPoint (Point3d (x[0], x[1], 0)); +} + +void Ng_AddBoundarySeg_2D (Ng_Mesh * mesh, int pi1, int pi2) +{ + Mesh * m = (Mesh*)mesh; + + Segment seg; + seg.p1 = pi1; + seg.p2 = pi2; + m->AddSegment (seg); +} + + +int Ng_GetNP_2D (Ng_Mesh * mesh) +{ + Mesh * m = (Mesh*)mesh; + return m->GetNP(); +} + +int Ng_GetNE_2D (Ng_Mesh * mesh) +{ + Mesh * m = (Mesh*)mesh; + return m->GetNSE(); +} + +int Ng_GetNSeg_2D (Ng_Mesh * mesh) +{ + Mesh * m = (Mesh*)mesh; + return m->GetNSeg(); +} + +void Ng_GetPoint_2D (Ng_Mesh * mesh, int num, double * x) +{ + Mesh * m = (Mesh*)mesh; + + Point3d & p = m->Point(num); + x[0] = p.X(); + x[1] = p.Y(); +} + +void Ng_GetElement_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum) +{ + const Element2d & el = ((Mesh*)mesh)->SurfaceElement(num); + for (int i = 1; i <= 3; i++) + pi[i-1] = el.PNum(i); + if (matnum) + *matnum = el.GetIndex(); +} + + +void Ng_GetSegment_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum) +{ + const Segment & seg = ((Mesh*)mesh)->LineSegment(num); + pi[0] = seg.p1; + pi[1] = seg.p2; + + if (matnum) + *matnum = seg.edgenr; +} + + + +Ng_Geometry_2D * Ng_LoadGeometry_2D (char * filename) +{ + SplineGeometry2d * geom = new SplineGeometry2d(); + geom -> Load (filename); + return (Ng_Geometry_2D *)geom; +} + +namespace netgen { + extern void MeshFromSpline2D (SplineGeometry2d & geometry, + Mesh *& mesh, + MeshingParameters & mp); +} + + +Ng_Result Ng_GenerateMesh_2D (Ng_Geometry_2D * geom, + Ng_Mesh ** mesh, + Ng_Meshing_Parameters * mp) +{ + MeshingParameters mparam; + mparam.maxh = mp->maxh; + mparam.meshsizefilename = mp->meshsize_filename; + + Mesh * m; + MeshFromSpline2D (*(SplineGeometry2d*)geom, m, mparam); + + cout << m->GetNSE() << " elements, " << m->GetNP() << " points" << endl; + + *mesh = (Ng_Mesh*)m; +} + + + + + + + + + + + + + + +ARRAY<STLReadTriangle> readtrias; //only before initstlgeometry +ARRAY<Point<3> > readedges; //only before init stlgeometry + +void Ng_SaveMesh(Ng_Mesh * mesh, char* filename) +{ + ((Mesh*)mesh)->Save(filename); +} + +// loads geometry from STL file +Ng_STL_Geometry * Ng_STL_LoadGeometry (char * filename, int binary) +{ + int i; + STLGeometry geom; + STLGeometry* geo; + ifstream ist(filename); + + if (binary) + { + geo = geom.LoadBinary(ist); + } + else + { + geo = geom.Load(ist); + } + + readtrias.SetSize(0); + readedges.SetSize(0); + + Point3d p; + Vec3d normal; + double p1[3]; + double p2[3]; + double p3[3]; + double n[3]; + + Ng_STL_Geometry * geo2 = Ng_STL_NewGeometry(); + + for (i = 1; i <= geo->GetNT(); i++) + { + const STLTriangle& t = geo->GetTriangle(i); + p = geo->GetPoint(t.PNum(1)); + p1[0] = p.X(); p1[1] = p.Y(); p1[2] = p.Z(); + p = geo->GetPoint(t.PNum(2)); + p2[0] = p.X(); p2[1] = p.Y(); p2[2] = p.Z(); + p = geo->GetPoint(t.PNum(3)); + p3[0] = p.X(); p3[1] = p.Y(); p3[2] = p.Z(); + normal = t.Normal(); + n[0] = normal.X(); n[1] = normal.Y(); n[2] = normal.Z(); + + Ng_STL_AddTriangle(geo2, p1, p2, p3, n); + } + + return geo2; +} + +// generate new STL Geometry +Ng_STL_Geometry * Ng_STL_NewGeometry () +{ + return (Ng_STL_Geometry*)(void*)new STLGeometry; +} + +// after adding triangles (and edges) initialize +Ng_Result Ng_STL_InitSTLGeometry (Ng_STL_Geometry * geom) +{ + STLGeometry* geo = (STLGeometry*)geom; + geo->InitSTLGeometry(readtrias); + readtrias.SetSize(0); + + if (readedges.Size() != 0) + { + int i; + /* + for (i = 1; i <= readedges.Size(); i+=2) + { + cout << "e(" << readedges.Get(i) << "," << readedges.Get(i+1) << ")" << endl; + } + */ + geo->AddEdges(readedges); + } + + if (geo->GetStatus() == STLTopology::STL_GOOD || geo->GetStatus() == STLTopology::STL_WARNING) return NG_OK; + return NG_SURFACE_INPUT_ERROR; +} + + // automatically generates edges: +Ng_Result Ng_STL_MakeEdges (Ng_STL_Geometry * geom, + Ng_Mesh* mesh, + Ng_Meshing_Parameters * mp) +{ + STLGeometry* stlgeometry = (STLGeometry*)geom; + Mesh* me = (Mesh*)mesh; + + MeshingParameters mparam; + + mparam.maxh = mp->maxh; + mparam.meshsizefilename = mp->meshsize_filename; + + me -> SetGlobalH (mparam.maxh); + me -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10), + stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10), + 0.3); + + if (mp->meshsize_filename) + { + ifstream infile (mp->meshsize_filename); + if (!infile.good()) return NG_FILE_NOT_FOUND; + me -> LoadLocalMeshSize (infile); + } + + STLMeshing (*stlgeometry, *me); + + stlgeometry->edgesfound = 1; + stlgeometry->surfacemeshed = 0; + stlgeometry->surfaceoptimized = 0; + stlgeometry->volumemeshed = 0; + + return NG_OK; +} + + +// generates mesh, empty mesh be already created. +Ng_Result Ng_STL_GenerateSurfaceMesh (Ng_STL_Geometry * geom, + Ng_Mesh* mesh, + Ng_Meshing_Parameters * mp) +{ + STLGeometry* stlgeometry = (STLGeometry*)geom; + Mesh* me = (Mesh*)mesh; + + MeshingParameters mparam; + + mparam.maxh = mp->maxh; + mparam.meshsizefilename = mp->meshsize_filename; + + /* + me -> SetGlobalH (mparam.maxh); + me -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10), + stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10), + 0.3); + */ + /* + STLMeshing (*stlgeometry, *me); + + stlgeometry->edgesfound = 1; + stlgeometry->surfacemeshed = 0; + stlgeometry->surfaceoptimized = 0; + stlgeometry->volumemeshed = 0; + */ + int retval = STLSurfaceMeshing (*stlgeometry, *me); + if (retval == MESHING3_OK) + { + (*mycout) << "Success !!!!" << endl; + stlgeometry->surfacemeshed = 1; + stlgeometry->surfaceoptimized = 0; + stlgeometry->volumemeshed = 0; + } + else if (retval == MESHING3_OUTERSTEPSEXCEEDED) + { + (*mycout) << "ERROR: Give up because of too many trials. Meshing aborted!" << endl; + } + else if (retval == MESHING3_TERMINATE) + { + (*mycout) << "Meshing Stopped!" << endl; + } + else + { + (*mycout) << "ERROR: Surface meshing not successful. Meshing aborted!" << endl; + } + + + STLSurfaceOptimization (*stlgeometry, *me, mparam); + + return NG_OK; +} + + + // fills STL Geometry + // positive orientation + // normal vector may be null-pointer +void Ng_STL_AddTriangle (Ng_STL_Geometry * geom, + double * p1, double * p2, double * p3, double * nv) +{ + Point<3> apts[3]; + apts[0] = Point<3>(p1[0],p1[1],p1[2]); + apts[1] = Point<3>(p2[0],p2[1],p2[2]); + apts[2] = Point<3>(p3[0],p3[1],p3[2]); + + Vec<3> n; + if (!nv) + n = Cross (apts[0]-apts[1], apts[0]-apts[2]); + else + n = Vec<3>(nv[0],nv[1],nv[2]); + + readtrias.Append(STLReadTriangle(apts,n)); +} + + // add (optional) edges: +void Ng_STL_AddEdge (Ng_STL_Geometry * geom, + double * p1, double * p2) +{ + readedges.Append(Point3d(p1[0],p1[1],p1[2])); + readedges.Append(Point3d(p2[0],p2[1],p2[2])); +} + + + +Ng_Meshing_Parameters :: Ng_Meshing_Parameters() +{ + maxh = 1000; + fineness = 0.5; + secondorder = 0; + meshsize_filename = 0; +} + + + + + +// compatibility functions: + +namespace netgen +{ + + char geomfilename[255]; + +void MyError (const char * ch) +{ + cerr << ch; +} + +//Destination for messages, errors, ... +void Ng_PrintDest(const char * s) +{ + (*mycout) << s << flush; +} + +double GetTime () +{ + return 0; +} + +void ResetTime () +{ + ; +} + +void MyBeep (int i) +{ + ; +} + +} diff --git a/Netgen/libsrc/interface/printdest.cpp b/Netgen/libsrc/interface/printdest.cpp new file mode 100644 index 0000000000..0db654d94f --- /dev/null +++ b/Netgen/libsrc/interface/printdest.cpp @@ -0,0 +1,11 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +namespace netgen +{ + //Destination for messages, errors, ... + void Ng_PrintDest(const char * s) + { + (*mycout) << s << flush; + } +} diff --git a/Netgen/libsrc/interface/readuser.cpp b/Netgen/libsrc/interface/readuser.cpp new file mode 100644 index 0000000000..0a9d2b6802 --- /dev/null +++ b/Netgen/libsrc/interface/readuser.cpp @@ -0,0 +1,372 @@ +// +// 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 char * filename) +{ + cout << "Read User File" << endl; + + int i, j; + + 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 (i = 1; i <= np; i++) + { + Point3d p; + in >> p.X() >> p.Y() >> p.Z(); + mesh.AddPoint (p); + } + + + in >> nbe; + // int invert = globflags.GetDefineFlag ("invertsurfacemesh"); + for (i = 1; i <= nbe; i++) + { + Element2d el; + int hi; + + el.SetIndex(1); + + for (j = 1; j <= 3; j++) + { + in >> 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); + } + + mesh.ClearFaceDescriptors(); + mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); + + cout << "points: " << np << " faces: " << nbe << endl; + } + + + + + + // Universal mesh (AVL) + if ( (strlen (filename) > 4) && + strcmp (&filename[strlen (filename)-4], ".unv") == 0 ) + { + int i, j, k; + + double h; + char reco[100]; + int np, nbe; + int invert; + + + ifstream in(filename); + + invert = 0; // globflags.GetDefineFlag ("invertsurfacemesh"); + double scale = 1; // globflags.GetNumFlag ("scale", 1); + + + while (in.good()) + { + in >> reco; + if (strcmp (reco, "NODES") == 0) + { + cout << "nodes found" << endl; + for (j = 1; j <= 4; j++) + in >> reco; // read dummy + + while (1) + { + int pi, hi; + double x, y, z; + Point3d p; + + in >> pi; + if (pi == -1) + break; + + in >> hi >> hi >> hi; + in >> p.X() >> p.Y() >> p.Z(); + + p.X() *= scale; + p.Y() *= scale; + p.Z() *= scale; + + + mesh.AddPoint (p); + } + } + + if (strcmp (reco, "ELEMENTS") == 0) + { + cout << "elements found" << endl; + for (j = 1; j <= 4; j++) + in >> reco; // read dummy + + while (1) + { + int hi; + in >> hi; + if (hi == -1) break; + for (j = 1; j <= 7; j++) + in >> hi; + + Element2d el; + el.SetIndex(1); + in >> el.PNum(1) >> el.PNum(2) >> el.PNum(3); + + if (invert) + Swap (el.PNum(2), el.PNum(3)); + mesh.AddSurfaceElement (el); + + for (j = 1; j <= 5; j++) + in >> hi; + } + } + } + + mesh.ClearFaceDescriptors(); + mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); + + 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); + 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; + + char buf[100]; + int np, ne, nse, i, j; + + ifstream in (filename); + + in >> np; + 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); + } + + + in >> nse; + for (i = 1; i <= nse; i++) + { + int mat, nelp; + in >> mat; + Element2d el (3); + el.SetIndex (mat); + for (j = 1; j <= 3; j++) + in >> el.PNum(j); + mesh.AddSurfaceElement (el); + } + } + + + 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 num, 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).X() < 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); + } + } + +} + +} diff --git a/Netgen/libsrc/interface/writeabaqus.cpp b/Netgen/libsrc/interface/writeabaqus.cpp new file mode 100644 index 0000000000..e9308b1472 --- /dev/null +++ b/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).X() << ", "; + outfile << mesh.Point(i).Y() << ", "; + outfile << mesh.Point(i).Z() << "\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); + int 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; + + 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/Netgen/libsrc/interface/writediffpack.cpp b/Netgen/libsrc/interface/writediffpack.cpp new file mode 100644 index 0000000000..25f9b2986f --- /dev/null +++ b/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.PointType(i) != 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.PointType(i) != 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/Netgen/libsrc/interface/writefeap.cpp b/Netgen/libsrc/interface/writefeap.cpp new file mode 100644 index 0000000000..817ee7c538 --- /dev/null +++ b/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, zz, n; + + 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).X()/scale << " "; + outfile.width(10); + outfile << mesh.Point(i).Y()/scale << " "; + outfile.width(10); + outfile << mesh.Point(i).Z()/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/Netgen/libsrc/interface/writefluent.cpp b/Netgen/libsrc/interface/writefluent.cpp new file mode 100644 index 0000000000..1a214089e3 --- /dev/null +++ b/Netgen/libsrc/interface/writefluent.cpp @@ -0,0 +1,200 @@ +// +// 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" + + + +static char* CHex(int i) +{ + static char str[100]; + sprintf(str,"%x",i); //hex + return str; +} + + + + +void WriteFluentFormat (const Mesh & mesh, + const string & filename) + +{ + // Simple output + 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 (c) Joachim Schoeberl and Johannes Gerstmayr\")" << 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 << CHex(face.PNum(2)) << " " << CHex(face.PNum(1)) << " " << CHex(face.PNum(3)) << " "; + outfile << CHex(i) << " " << CHex(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 << CHex(surfaceelp.Get(i).I1()) << " " << CHex(surfaceelp.Get(i).I2()) << " " << CHex(surfaceelp.Get(i).I3()) << " "; + outfile << CHex(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/Netgen/libsrc/interface/writepermas.cpp b/Netgen/libsrc/interface/writepermas.cpp new file mode 100644 index 0000000000..824a36bc9b --- /dev/null +++ b/Netgen/libsrc/interface/writepermas.cpp @@ -0,0 +1,169 @@ +// +// Write Permas file +// for Intes GmbH, Stuttgart +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +namespace netgen +{ +#include "writeuser.hpp" + + + +void WritePermasFormat (const Mesh & mesh, + const string & filename) + +{ + + ofstream outfile (filename.c_str()); + + outfile.precision(8); + + 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; + 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; + + for (i = 1; i <= np; i++) + { + outfile << i << " "; + outfile << mesh.Point(i).X() << " "; + outfile << mesh.Point(i).Y() << " "; + outfile << mesh.Point(i).Z() << "\n"; + } +} + + +} diff --git a/Netgen/libsrc/interface/writetecplot.cpp b/Netgen/libsrc/interface/writetecplot.cpp new file mode 100644 index 0000000000..1f5e01351b --- /dev/null +++ b/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 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); + } + } + + + 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) + { + geom.GetSurface(j) -> GetNormalVector ( mesh.Point(i), n ); + + outfile << mesh.Point(i).X() << " " /* Knoten Koordinaten */ + << mesh.Point(i).Y() << " " + << mesh.Point(i).Z() << " " + << 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 (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + INDEX_3 i3; + for (j = 1; j <= 3; j++) + i3.I(j) = el.PNum(j); + i3.Sort(); + + int elind = face2volelement.Get(i3); + } + } + } +} + + +} diff --git a/Netgen/libsrc/interface/writetochnog.cpp b/Netgen/libsrc/interface/writetochnog.cpp new file mode 100644 index 0000000000..50546dc2d1 --- /dev/null +++ b/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, k; + + for (i = 1; i <= np; i++) + { + outfile << "node " << " " << i << " "; + outfile << mesh.Point(i).X() << " "; + outfile << mesh.Point(i).Y() << " "; + outfile << mesh.Point(i).Z() << "\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/Netgen/libsrc/interface/writeuser.cpp b/Netgen/libsrc/interface/writeuser.cpp new file mode 100644 index 0000000000..1909eb2193 --- /dev/null +++ b/Netgen/libsrc/interface/writeuser.cpp @@ -0,0 +1,729 @@ +// +// 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) +{ + char *types[] = + { + "Neutral Format", + "Surface Mesh Format" , + "DIFFPACK Format", + "TecPlot Format", + "Tochnog Format", + "Abaqus Format", + "Fluent Format", + "Permas Format", + "FEAP Format", + "STL Format", + "VRML Format", + "Fepp Format", + // { "Chemnitz Format" }, + 0 + }; + + for (int i = 0; types[i]; i++) + names.Append (types[i]); +} + + + +bool WriteUserFormat (const string & format, + const Mesh & mesh, + const CSGeometry & geom, + const string & filename) +{ + cout << "Write user format " << format << endl; + + 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 == "STL Format") + WriteSTLFormat (mesh, filename); + + else if (format == "VRML Format") + WriteVRMLFormat (mesh, 1, filename); + + else if (format == "Fepp Format") + WriteFEPPFormat (mesh, geom, filename); + + else if (format == "Chemnitz Format") + WriteUserChemnitz (mesh, filename); + + 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 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() << " "; + outfile.width(9); + outfile << p.Z() << "\n"; + } + + 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"; + } +} + + + + + + + + + +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 = 1; j <= 3; j++) + { + outfile.width(10); + outfile << mesh.Point(i).X(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, j, k; + + 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; +} + + + + + +/* + * + * 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, k, l; + + 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, k, l; + + 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); + */ + } +} + + + + + + + + + + + + + + + +#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/Netgen/libsrc/interface/writeuser.hpp b/Netgen/libsrc/interface/writeuser.hpp new file mode 100644 index 0000000000..26e8f8eeb1 --- /dev/null +++ b/Netgen/libsrc/interface/writeuser.hpp @@ -0,0 +1,101 @@ +#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 char * filename); + +extern +void ImportSolution (const char * 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); + +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 WriteUserChemnitz (const Mesh & mesh, + 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 RegisterUserFormats (ARRAY<const char*> & names); +extern bool WriteUserFormat (const string & format, + const Mesh & mesh, + const CSGeometry & geom, + const string & filename); +#endif diff --git a/Netgen/libsrc/interface/wuchemnitz.cpp b/Netgen/libsrc/interface/wuchemnitz.cpp new file mode 100644 index 0000000000..306cbe6268 --- /dev/null +++ b/Netgen/libsrc/interface/wuchemnitz.cpp @@ -0,0 +1,309 @@ +// 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: + VOLELEMENT () {}; + int domnr, p1, p2, p3, p4; + int faces[4]; + }; + +class SURFELEMENT + { + public: + SURFELEMENT () { }; + int snr, p1, p2, p3; + }; + + +class FACE + { + public: + FACE () { }; + int p1, p2, p3; + int edges[3]; + }; + +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; + } + 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; + } + 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/Netgen/libsrc/linalg/Makefile b/Netgen/libsrc/linalg/Makefile new file mode 100644 index 0000000000..a3ca3763d9 --- /dev/null +++ b/Netgen/libsrc/linalg/Makefile @@ -0,0 +1,13 @@ +# +# Makefile for linear algebra library +# +src = densemat.cpp vector.cpp polynomial.cpp +# +lib = la +libpath = libsrc/linalg +# +# +include ../makefile.inc +# + + diff --git a/Netgen/libsrc/linalg/basemat.cpp b/Netgen/libsrc/linalg/basemat.cpp new file mode 100644 index 0000000000..49fd4c2e41 --- /dev/null +++ b/Netgen/libsrc/linalg/basemat.cpp @@ -0,0 +1,465 @@ +#include <mystdlib.h> +#include <linalg.hpp> + + +// ofstream (*myerr) ("error.out"); +// ofstream (*myerr) ("NUL"); + + +namespace netgen +{ + +double BaseMatrix :: shit = 0; + + +BaseMatrix :: BaseMatrix () + { + height = width = 0; + symmetric = 0; + } + +BaseMatrix :: BaseMatrix (INDEX h, INDEX w) + { + if (!w) w = h; + height = h; + width = w; + symmetric = 0; + } + +void BaseMatrix :: SetSize (INDEX h, INDEX w) + { + if (!w) w = h; + height = h; + width = w; + } + +void BaseMatrix :: SetSymmetric (int sym) + { + symmetric = sym; + } + +double & BaseMatrix :: operator() (INDEX, INDEX) + { + (*myerr) << "BaseMatrix: operator() called" << endl; + return shit; + } + +double BaseMatrix :: operator() (INDEX, INDEX) const + { + (*myerr) << "BaseMatrix: operator() called" << endl; + return 0; + } + + + +ostream & operator<<(ostream & s, const BaseMatrix & m) + { + return m.Print (s); + } + +ostream & BaseMatrix :: Print (ostream & s) const + { + if (Symmetric()) s << "Symmetric" << endl; + for (INDEX i = 1; i <= Height(); i++) + { + for (INDEX j = 1; j < Width(); j++) + s << (*this)(i, j) << " "; + s << (*this)(i, Width()) << endl; + } + + return s; + } + + + +TempVector BaseMatrix :: operator* (const BaseVector & v) const + { + Vector * prod = new Vector(Height()); + + if (Width() != v.Length()) + { + (*myerr) << "\nMatrix and Vector don't fit 1" << endl; + } + else if (Height() != prod->Length()) + { + (*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl; + } + else + { + Mult (v, *prod); + } + + return *prod; + } + + + +DenseMatrix operator* (const BaseMatrix & m1, const BaseMatrix & m2) + { + DenseMatrix temp (m1.Height(), m2.Width()); + double sum; + + if (m1.Width() != 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 (INDEX i = 1; i <= m1.Height(); i++) + for (INDEX j = 1; j <= m2.Width(); j++) + { + sum = 0; + for (INDEX k = 1; k <= m1.Width(); k++) + sum += m1(i, k) * m2(k, j); + temp(i, j) = sum; + } + } + return temp; + } + + +DenseMatrix operator+ (const BaseMatrix & m1, const BaseMatrix & m2) + { + DenseMatrix temp (m1.Height(), m1.Width()); + INDEX 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(i, j) = m1(i, j) + m2(i, j); + } + } + return temp; + } + + +void BaseMatrix :: Mult (const BaseVector & /* v */, + BaseVector & /* prod */) const + { + (*myerr) << "BaseMatrix :: Mult called" << endl; + } + +void BaseMatrix :: MultTrans (const BaseVector & v, + BaseVector & prod) const + { + if (Symmetric()) + Mult (v, prod); + else + (*myerr) << "BaseMatrix :: MultTrans called for non symmetric matrix" << endl; + } + +void BaseMatrix :: Residuum (const BaseVector & x, + const BaseVector & b, BaseVector & res) const + { + Mult (x, res); + res *= -1; + res.Add (1, b); + } + +void BaseMatrix :: ResiduumTrans (const BaseVector & x, + const BaseVector & b, BaseVector & res) const + { + MultTrans (x, res); + res *= -1; + res.Add (1, b); + } + +BaseMatrix * BaseMatrix :: Copy () const + { + (*myerr) << "BaseMatrix :: Copy called" << endl; + return NULL; + } + + +BaseVector * BaseMatrix :: CreateVector () const + { + return new Vector (Height()); + } + + + +/* +void BaseMatrix :: Mult (const Vector & v, Vector & prod) const + { + double sum; + + prod.SetLength (Height()); + + if (Width() != v.Length()) + { + (*myerr) << "\nMatrix and Vector don't fit 2" << endl; + } + else if (Height() != prod.Length()) + { + (*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl; + } + else + { + for (INDEX i = 1; i <= Height(); i++) + { + sum = 0; + + for (INDEX j = 1; j <= Width(); j++) + sum += (*this)(i,j) * v.Get(j); + + prod.Set (i, sum); + } + } + } + + +void BaseMatrix :: MultTrans (const Vector & v, Vector & prod) const + { + double sum; + + prod.SetLength (Width()); + + if (Height() != v.Length()) + { + (*myerr) << "\nMatrix and Vector don't fit 3" << endl; + } + else if (Width() != prod.Length()) + { + (*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl; + } + else + { + for (INDEX i = 1; i <= Width(); i++) + { + sum = 0; + + for (INDEX j = 1; j <= Height(); j++) + sum += (*this)(j, i) * v.Get(j); + + prod.Set (i, sum); + } + } + } + + +void BaseMatrix :: Residuum (const Vector & x, const Vector & b, Vector & res) const + { + double sum; + + res.SetLength (Height()); + + if (Width() != x.Length() || Height() != b.Length()) + { + (*myerr) << "\nMatrix and Vector don't fit 4" << endl; + } + else if (Height() != res.Length()) + { + (*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl; + } + else + { + for (INDEX i = 1; i <= Height(); i++) + { + sum = b.Get(i); + + for (INDEX j = 1; j <= Width(); j++) + sum -= (*this)(i,j) * x.Get(j); + + res.Set (i, sum); + } + } + } +*/ + + + + + + + +void BaseMatrix :: SolveDestroy (const Vector & v, Vector & sol) + { + INDEX i, j, k; + double q; + + if (Width() != Height()) + { + (*myerr) << "SolveDestroy: Matrix not square"; + return; + } + if (Width() != v.Length()) + { + (*myerr) << "SolveDestroy: Matrix and Vector don't fit"; + return; + } + + sol = v; + if (Height() != sol.Length()) + { + (*myerr) << "SolveDestroy: Solution Vector not ok"; + return; + } + + for (i = 1; i <= Height(); i++) + { + for (j = i+1; j <= Height(); j++) + { + q=(*this)(j,i) / (*this)(i,i); + for (k = i+1; k <= Height(); k++) + { + (*this)(j, k) -= q * (*this)(i,k); + } + sol.Elem(j) -= q * sol.Get(i); + } + } + + for (i = Height(); i >= 1; i--) + { + q = sol(i); + for (j = i+1; j <= Height(); j++) + { + q -= (*this)(i,j) * sol.Get(j); + } + sol.Set(i, q / (*this)(i,i)); + } + } + +void BaseMatrix :: Solve (const Vector & v, Vector & sol) const + { + BaseMatrix * temp = Copy(); + + if (temp->Height() != Height()) + { + (*myerr) << "Solve: Matrix temp not allocated" << endl; + return; + } + + temp->SolveDestroy (v, sol); + + delete temp; + } + + +Vector BaseMatrix :: SolveDestroyFunc (const Vector & /* b */) const +{ + return Vector(0); +} + + + +Vector BaseMatrix :: Solve (const Vector & v) const + { + Vector sol (v.Length()); + + if (Width() != Height()) + { + (*myerr) << "Solve: Matrix not square"; + return v; + } + if (Width() != v.Length()) + { + (*myerr) << "Solve: Matrix and Vector don't fit"; + return v; + } + if (Width() != sol.Length()) + { + (*myerr) << "Solve: Vector sol not allocated" << endl; + } + + Solve (v, sol); + + return sol; + } + + + + + + + +void BaseMatrix :: LU_Decomposition (DenseMatrix & l, DenseMatrix & u) const + { + INDEX i, j ,k; + double sum; + l.SetSize (Width()); + u.SetSize (Width()); + + for (i = 1; i <= Width(); i++) + for (j = 1; j <= Width(); j++) + l(i, j) = u(i, j) = 0; + + for (i = 1; i <= Width(); i++) + { + for (k = 1; k < i; k++) + { + sum = (*this)(i, k); + for (j = 1; j < k; j++) + sum -= l(i, j) * u(j, k); + l(i, k) = sum / u(k, k); + } + l(i, i) = 1; + + for (k = i; k <= Width(); k++) + { + sum = (*this)(i, k); + for (j = 1; j < i; j++) + sum -= l(i, j) * u(j, k); + u(i, k) = sum; + } + } + } + + + +void Transpose (const BaseMatrix & m1, DenseMatrix & m2) + { + m2.SetSize (m1.Width(), m1.Height()); + INDEX i, j; + + for (i = 1; i <= m1.Height(); i++) + for (j = 1; j <= m1.Width(); j++) + m2(j, i) = m1(i, j); + } + + + +DenseMatrix * BaseMatrix :: MakeDenseMatrix () const +{ + DenseMatrix * dmat = new DenseMatrix (Height(), Width()); + dmat -> SetSymmetric(Symmetric()); + + Vector x(Width()), y(Height()); + INDEX i, j; + + for (i = 1; i <= Width(); i++) + { + x = 0; + x.Elem(i) = 1; + Mult (x, y); + + for (j = 1; j <= Height(); j++) + dmat->Elem(j, i) = y.Get(j); + } + + return dmat; +} + + +BaseMatrix * BaseMatrix :: InverseMatrix (const BitArray * /* inner */) const +{ + (*mycout) << "called basematrix::inversemarix" << endl; + return NULL; +} + + + +} diff --git a/Netgen/libsrc/linalg/basemat.hpp b/Netgen/libsrc/linalg/basemat.hpp new file mode 100644 index 0000000000..89a9e21411 --- /dev/null +++ b/Netgen/libsrc/linalg/basemat.hpp @@ -0,0 +1,105 @@ +#ifndef FILE_BASEMAT +#define FILE_BASEMAT + +/**************************************************************************/ +/* File: basemat.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Oct. 94 */ +/**************************************************************************/ + +/* + Base type for linear operator +*/ + +class DenseMatrix; + +/// +class BaseMatrix +{ +protected: + /// + INDEX height, width; + /// + int symmetric; + /// + static double shit; + +public: + /// + BaseMatrix (); + /// + BaseMatrix (INDEX h, INDEX w = 0); + /// + virtual ~BaseMatrix () { }; + + /// + INDEX Width () const { return width; } + /// + INDEX Height () const { return height; } + /// + int Symmetric () const { return symmetric; } + + /// + virtual void SetSize (INDEX h, INDEX w = 0); + /// + virtual void SetSymmetric (int sym = 1); + + /// + virtual double & operator() (INDEX i, INDEX j); + /// + virtual double operator() (INDEX i, INDEX j) const; + + /// + friend ostream & operator<<(ostream & s, const BaseMatrix & m); + /// + virtual ostream & Print (ostream & s) const; + + /// + TempVector operator* (const BaseVector & v) const; + + + /// + virtual void Mult (const BaseVector & v, BaseVector & prod) const; + /// + virtual void MultTrans (const BaseVector & v, BaseVector & prod) const; + /// + virtual void Residuum (const BaseVector & x, const BaseVector & b, BaseVector & res) const; + /// + virtual void ResiduumTrans (const BaseVector & x, const BaseVector & b, BaseVector & res) const; + // virtual double EvaluateBilinearform (const BaseVector & x); + + virtual BaseMatrix * Copy () const; + /// + virtual BaseVector * CreateVector () const; + + /// + virtual void AddElementMatrix (const ARRAY<INDEX> & /* pnum */, + const BaseMatrix & /* elemmat */) { }; + /// + virtual void MultElementMatrix (const ARRAY<INDEX> & /* pnum */, + const BaseVector & /* x */, BaseVector & /* y */) { }; + /// + virtual void MultTransElementMatrix (const ARRAY<INDEX> & /* pnum */, + const BaseVector & /* x */, BaseVector & /* y */) { }; + + + /// + virtual DenseMatrix * MakeDenseMatrix () const; + /// + virtual BaseMatrix * InverseMatrix (const class BitArray * inner = NULL) + const; + + /// + virtual void SolveDestroy (const Vector & b, Vector & x); + /// + void Solve (const Vector & b, Vector & x) const; + /// + virtual Vector SolveDestroyFunc (const Vector & b) const; + /// + Vector Solve (const Vector & b) const; + /// + virtual void LU_Decomposition (DenseMatrix & l, DenseMatrix & u) const; +}; + + +#endif diff --git a/Netgen/libsrc/linalg/densemat.cpp b/Netgen/libsrc/linalg/densemat.cpp new file mode 100644 index 0000000000..d15c123e0d --- /dev/null +++ b/Netgen/libsrc/linalg/densemat.cpp @@ -0,0 +1,1443 @@ +#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; + 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; + } + + + + + /* +double & DenseMatrix :: operator() (int i, int j) +{ + if (i >= 1 && j >= 1 && i <= height && j <= width) + return Elem(i,j); + else (*myerr) << "DenseMatrix: index (" << i << "," << j << ") out of range (1.." + << height << ",1.." << width << ")\n"; + static double dummy = 0; + return dummy; +} + + double DenseMatrix :: operator() (int i, int j) const + { + if (i >= 1 && j >= 1 && i <= height && j <= width) + return Get(i,j); + else (*myerr) << "DenseMatrix: index (" << i << "," << j << ") out of range (1.." + << height << ",1.." << width << ")\n"; + + static double dummy = 0; + return dummy; + } + */ + +DenseMatrix & DenseMatrix :: operator= (double v) + { + int i; + double * p = data; + + if (data) + for (i = width*height; i > 0; i--, p++) + *p = v; + + return *this; + } + + + +DenseMatrix & DenseMatrix :: operator*= (double v) + { + int i; + double * p = data; + + if (data) + for (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 Get(1, 1); + case 2: return Get(1) * Get(4) - Get(2) * Get(3); + + case 3: return Get(1) * Get(5) * Get(9) + + Get(2) * Get(6) * Get(7) + + Get(3) * Get(4) * Get(8) + - Get(1) * Get(6) * Get(8) + - Get(2) * Get(4) * Get(9) + - Get(3) * Get(5) * Get(7); + default: + { + (*myerr) << "Matrix :: Det: general size not implemented (size=" << width << ")" << endl; + return 0; + } + } + } + + +void CalcInverse (const DenseMatrix & m1, DenseMatrix & m2) + { + // int i, j, k, n; + double det; + // DenseMatrix m1 = hm1; + + 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; + return; + } + + det = 1e0 / det; + switch (m1.width) + { + case 1: + { + m2.Set(1, 1, det); + return; + } + case 2: + { + m2.Set(1, 1, det * m1.Get(4)); + m2.Set(2, 2, det * m1.Get(1)); + m2.Set(1, 2, - det * m1.Get(2)); + m2.Set(2, 1, - det * m1.Get(3)); + return; + } + case 3: + { + m2.Set(1, 1, det * (m1.Get(5) * m1.Get(9) - m1.Get(6) * m1.Get(8))); + m2.Set(2, 1, -det * (m1.Get(4) * m1.Get(9) - m1.Get(6) * m1.Get(7))); + m2.Set(3, 1, det * (m1.Get(4) * m1.Get(8) - m1.Get(5) * m1.Get(7))); + + m2.Set(1, 2, -det * (m1.Get(2) * m1.Get(9) - m1.Get(3) * m1.Get(8))); + m2.Set(2, 2, det * (m1.Get(1) * m1.Get(9) - m1.Get(3) * m1.Get(7))); + m2.Set(3, 2, -det * (m1.Get(1) * m1.Get(8) - m1.Get(2) * m1.Get(7))); + + m2.Set(1, 3, det * (m1.Get(2) * m1.Get(6) - m1.Get(3) * m1.Get(5))); + m2.Set(2, 3, -det * (m1.Get(1) * m1.Get(6) - m1.Get(3) * m1.Get(4))); + m2.Set(3, 3, det * (m1.Get(1) * m1.Get(5) - m1.Get(2) * m1.Get(4))); + 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; + 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.Elem(p.Get(k)) = m2.Get(i, k); + for (k = 1; k <= n; k++) + m2.Elem(i, k) = hv.Get(k); + } + + + + /* + 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); + } + } + } + + + +#ifdef ABC +BaseMatrix * DenseMatrix :: InverseMatrix (const BitArray * /* inner */) const +{ + if (Height() != Width()) + { + (*myerr) << "BaseMatrix::InverseMatrix(): Matrix not symmetric" << endl; + return new DenseMatrix(1); + } + else + { + if (Symmetric()) + { + (*mycout) << "Invmat not available" << endl; + BaseMatrix * invmat = NULL; + return invmat; + } + + DenseMatrix * invmat = new DenseMatrix (Height()); + + CalcInverse (*this, *invmat); + return invmat; + } +} +#endif + + + +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.Get(1); + + prod = 0; + + for (i = 1; i <= h; i++) + { + double val = *pv; + ++pv; + + double * pprod = &prod.Elem(1); + + 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 i, j; + int h = Height(); + int w = Width(); + const double * mp = &Get(1, 1); + + for (i = 1; i <= h; i++) + { + sum = b.Get(i); + const double * xp = &x.Get(1); + + for (j = 1; j <= w; ++j, ++mp, ++xp) + sum -= *mp * *xp; + + res.Elem(i) = 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.Elem(i) = 1 / sqrt(x); + } + else + { + Elem(j, i) = x * p.Get(i); + } + } + } + + for (i = 1; i <= n; i++) + Elem(i, i) = 1 / p.Get(i); + + // A = L L^t + // L stored in left-lower triangle + + + sol = v; + + // Solve L sol = sol + + for (i = 1; i <= n; i++) + { + double val = sol.Get(i); + + const double * pij = &Get(i, 1); + const double * solj = &sol.Get(1); + + for (j = 1; j < i; j++, ++pij, ++solj) + val -= *pij * *solj; + // for (j = 1; j < i; j++) + // val -= Get(i, j) * sol.Get(j); + + sol.Elem(i) = val / Get(i, i); + } + + // Solve L^t sol = sol + + for (i = n; i >= 1; i--) + { + double val = sol.Get(i) / Get(i, i); + sol.Elem(i) = val; + + double * solj = &sol.Elem(1); + 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 i, j, k, n = Height(); + for (i = 1; i <= n; i++) + { + for (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 (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.Elem(j) -= q * sol.Get(i); + } + } + } + + for (i = n; i >= 1; i--) + { + q = sol.Get(i); + for (j = i+1; j <= n; j++) + q -= Get(i,j) * sol.Get(j); + + sol.Elem(i) = 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/Netgen/libsrc/linalg/densemat.hpp b/Netgen/libsrc/linalg/densemat.hpp new file mode 100644 index 0000000000..f2dc9bd605 --- /dev/null +++ b/Netgen/libsrc/linalg/densemat.hpp @@ -0,0 +1,260 @@ +#ifndef FILE_DENSEMAT +#define FILE_DENSEMAT + +/**************************************************************************/ +/* File: densemat.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Oct. 94 */ +/**************************************************************************/ + +/** + Data type dense matrix +*/ + + +#include <assert.h> + +class DenseMatrix +{ +protected: + int height; + int width; + double * data; + +public: + /// + DenseMatrix (); + /// + DenseMatrix (int h, int w = 0); + /// + DenseMatrix (const DenseMatrix & m2); + /// + ~DenseMatrix (); + + /// + 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]; } + + /// + DenseMatrix & operator= (const DenseMatrix & m2); + /// + DenseMatrix & operator+= (const DenseMatrix & m2); + /// + DenseMatrix & operator-= (const DenseMatrix & m2); + + /// + DenseMatrix & operator= (double v); + /// + DenseMatrix & operator*= (double v); + + /// + void Mult (const FlatVector & v, FlatVector & prod) const + { + double sum; + const double * mp, * sp; + double * dp; + + if (prod.Size() != height) + { + cerr << "Mult: wrong vector size " << endl; + assert (1); + // prod.SetSize (height); + } + +#ifdef DEBUG + 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.Elem(1); + for (int i = 1; i <= height; i++) + { + sum = 0; + sp = &v.Get(1); + + for (INDEX j = 1; j <= width; j++) + { + // sum += Get(i,j) * v.Get(j); + sum += *mp * *sp; + mp++; + sp++; + } + + *dp = sum; + dp++; + } + } + } + + /// + void MultTrans (const Vector & v, Vector & prod) const; + /// + void Residuum (const Vector & x, const Vector & b, Vector & res) const; + /// + 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); + /// + void Solve (const Vector & b, Vector & x) const; + /// + void SolveDestroy (const Vector & b, Vector & x); + /// + const double & Get(INDEX i, INDEX j) const { return data[(i-1)*width+j-1]; } + /// + const double & Get(INDEX i) const { return data[i-1]; } + /// + void Set(INDEX i, INDEX j, double v) { data[(i-1)*width+j-1] = v; } + /// + double & Elem(INDEX i, INDEX j) { return data[(i-1)*width+j-1]; } + /// + const double & ConstElem(INDEX i, INDEX 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; } + + /* + /// + virtual double & operator() (INDEX i, INDEX j); + /// + virtual double operator() (INDEX i, INDEX j) const; + */ + + /// + MatrixFixWidth & operator= (double v) + { + for (int i = 0; i < height*WIDTH; i++) + data[i] = 0; + } + + /// + 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]; } + + + + 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]; } +}; + + + + + +#endif diff --git a/Netgen/libsrc/linalg/linalg.hpp b/Netgen/libsrc/linalg/linalg.hpp new file mode 100644 index 0000000000..3dd73e8ef0 --- /dev/null +++ b/Netgen/libsrc/linalg/linalg.hpp @@ -0,0 +1,33 @@ +#ifndef FILE_LINALG +#define FILE_LINALG + +/* *************************************************************************/ +/* File: linalg.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Oct. 94 */ +/* *************************************************************************/ + +/* + + Data types for basic linear algebra + more data types are found in linalgl.hpp + + The basic concepts include the data types + + Vector + SparseMatrix + DenseMatrix + +*/ + + +#include <myadt.hpp> +namespace netgen +{ +#include "vector.hpp" +#include "densemat.hpp" +#include "polynomial.hpp" +} +#endif + + diff --git a/Netgen/libsrc/linalg/polynomial.cpp b/Netgen/libsrc/linalg/polynomial.cpp new file mode 100644 index 0000000000..f947e0a191 --- /dev/null +++ b/Netgen/libsrc/linalg/polynomial.cpp @@ -0,0 +1,216 @@ +#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; + + // (*testout) << "maxv = " << maxv << " =~= "; + + /* + double x, y; + maxv = -1e8; + double val; + for (x = 0; x <= 1.01; x += 0.1) + for (y = 0; y <= 1.01; y += 0.1) + { + val = Value (x, y); + if (val > maxv) + maxv = val; + } + + // (*testout) << maxv << endl; + 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/Netgen/libsrc/linalg/polynomial.hpp b/Netgen/libsrc/linalg/polynomial.hpp new file mode 100644 index 0000000000..3108d4dd72 --- /dev/null +++ b/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/Netgen/libsrc/linalg/sparsmat.cpp b/Netgen/libsrc/linalg/sparsmat.cpp new file mode 100644 index 0000000000..cb2f32a233 --- /dev/null +++ b/Netgen/libsrc/linalg/sparsmat.cpp @@ -0,0 +1,1703 @@ +#include <mystdlib.h> + +#include <linalg.hpp> + + +namespace netgen +{ +MatrixGraph :: MatrixGraph (int size, int aincrement) +{ + int i; + increment = aincrement; + + lines.SetSize (size); + for (i = 1;i <= size; i++) + { + lines.Elem(i).allocsize = increment; + lines.Elem(i).size = 1; + lines.Elem(i).diag = 1; + lines.Elem(i).col = new INDEX[increment]; + lines.Elem(i).col[0] = i; + } +} + +MatrixGraph :: MatrixGraph (const ARRAY<int> & linesize) +{ + INDEX i; + INDEX n = linesize.Size(); + INDEX sum = 0; + INDEX * cola; + + lines.SetSize (n); + increment = 0; + + for (i = 1; i <= n; i++) + sum += linesize.Get(i); + + cola = new INDEX[sum]; + + sum = 0; + for (i = 1; i <= n; i++) + { + lines.Elem(i).allocsize=linesize.Get(i); + lines.Elem(i).size = 1; + lines.Elem(i).diag = 1; + lines.Elem(i).col = &cola[sum]; + cola[sum] = i; + sum += linesize.Get(i); + } +} + +int MatrixGraph :: GetPosition (INDEX i, INDEX j) const +{ + int k; + + INDEX * ip = lines.Get(i).col; + INDEX n = lines.Get(i).size; + for (k = 1; k <= n; k++, ip++) + { + if (j == *ip) return k; + } + + return 0; + + /* + // quick search: + + const INDEX * ip = lines.Get(i).col; + int max = lines.Get(i).size; + + int l = 0, k = 1, newind; + + while (k < max) + k <<= 1; + + while (k > 0) + { + k >>= 1; + newind = k+l; + if (newind >= max) continue; + if (ip[newind] <= j) + l += k; + } + + if (l < max && ip[l] == j) + return l+1; + + return 0; + */ +} + + + +int MatrixGraph :: CreatePosition (INDEX i, INDEX j) + { + int k; + MatrixGraph::linestruct * lin = &lines.Elem(i); + + + + for (k = 1; k <= lin->size; k++) + { + if (lin->col[k-1] == j) + return 0; + if (lin->col[k-1] > j) + break; + } + + // k ... position to enter new element + + if (lin->size == lin->allocsize) + { + INDEX * tmpcol = new INDEX[lin->size + increment]; + memcpy (tmpcol, lin->col, sizeof(INDEX) * lin->size); + delete lin->col; + lin->col = tmpcol; + lin->allocsize+=increment; + } + + if (k <= lin->size) + memmove (&lin->col[k], &lin->col[k-1], + sizeof(INDEX) * (lin->size + 1 - k)); + + lin->col[k-1] = j; + lin->size++; + if (j < i) lin->diag++; + + return 1; + } + + + +double & SparseMatrix :: operator() (INDEX i, INDEX j) +{ + if (i >= 1 && i <= height && j >= 1 && j <= width) + return Elem(i, j); + else + { + (*myerr) << "SparseMatirx::operator(): out of range" << endl; + return shit; + } +} + +double SparseMatrix :: operator() (INDEX i, INDEX j) const +{ + if (i >= 1 && i <= height && j >= 1 && j <= width) + return Get(i, j); + else + { + (*myerr) << "SparseMatirx::operator(): out of range" << endl; + return shit; + } +} + + + + + + +SparseMatrix :: SparseMatrix (INDEX h, INDEX w) + : BaseMatrix (h, w) +{ + ; +} + + + + +void SparseMatrix :: Mult (const BaseVector & bv, BaseVector & bprod) const + { + double sum, vi; + INDEX i, j, n; + + const INDEX * col; + const double * valp; + + const Vector & v = bv.CastToVector(); + Vector & prod = bprod.CastToVector(); + + prod.SetLength (Height()); + + /* + if (prod.Length() != Height() || v.Length() != Width()) + { + (*myerr) << "SparseMatrix::Mult: Dimensions don't fit" << endl; + return; + } + */ + + if (!Symmetric()) + { + n = Height(); + INDEX w = Width(); + + /* + const MatrixGraph::linestruct * linep = &graph->lines.Get(1); + + for (i = 1; i <= n; i++) + { + sum = 0; + col = linep->col; + valp = data.Get(i); + + for (j = 0; j < linep->size; j++, valp++, col++) + sum += *valp * v.Get(*col); + + linep++; + prod.Set (i, sum); + } + */ + + const MatrixGraph::linestruct * linep = &graph->lines.Get(1); + const double * vp = &v.Get(1); + vp--; + + for (i = 1; i <= n; i++) + { + sum = 0; + col = linep->col; + valp = data.Get(i); + const int ls = linep->size; + + if (i <= w) + for (j = 0; j < ls; j++) + sum += valp[j] * vp[col[j]]; + else + // decrement one, because of diagonal element outside + for (j = 0; j < ls-1; j++) + sum += valp[j] * vp[col[j]]; + + + linep++; + prod.Set (i, sum); + } + + } + else + { + prod = 0; + n = Height(); + + const MatrixGraph::linestruct * linep = &graph->lines.Get(1); + + for (i = 1; i <= n; i++) + { + sum = 0; + // col = graph->lines.Get(i).col; + col = linep->col; + valp = data.Get(i); + vi = v.Get(i); + + for (j = linep->diag-1; j > 0; j--, col++, valp++) + { + sum += (*valp) * v.Get(*col); + prod.Elem(*col) += (*valp) * vi; + } + + linep++; + sum += (*valp) * v.Get(*col); + prod.Elem(i) += sum; + } + } + } + +void SparseMatrix :: MultTrans (const BaseVector & bv, BaseVector & bprod) const + { + INDEX i, j, n, coln; + const Vector & v = bv.CastToVector(); + Vector & prod = bprod.CastToVector(); + const INDEX * col; + const double * valp; + double val; + + prod.SetLength (Width()); + + if (prod.Length() != Width() || v.Length() != Height()) + { + (*myerr) << "SparseMatrix::Mult: Dimensions don't fit" << endl; + return; + } + + if (!Symmetric()) + { + n = Height(); + prod = 0; + + for (i = 1; i <= n; i++) + { + col = graph->lines.Get(i).col; + valp = data.Get(i); + coln = graph->lines.Get(i).size; + val = v.Get(i); + + // lin = &lins.Get(i); + // col = lin->col; + // val = v.Get(i); + + for (j = 1; j <= coln; j++, col++, valp++) + prod.Elem(*col) += (*valp) * val; + } + } + else + { + Mult (v, prod); + } + } + + + + +void SparseMatrix :: Residuum (const BaseVector & bx, const BaseVector & bb, + BaseVector & bres) const + { + BaseMatrix :: Residuum (bx, bb, bres); + /* + double sum, xi; + INDEX i, j, n; + colstruct * col; + const linestruct * lin; + const Vector & x = bx.CastToVector(); + const Vector & b = bb.CastToVector(); + Vector & res = bres.CastToVector(); + + res.SetLength (b.Length()); + + if (res.Length() != b.Length() || b.Length() != Height() || + x.Length() != Width()) + { + (*myerr) << "SparseMatrix::Residuum: Dimensions don't fit" << endl; + return; + } + + n = Height(); + if (!Symmetric()) + { + for (i = 1; i <= Height(); i++) + { + lin = &lins.Get(i); + sum = b.Get(i); + col = lin->col; + + for (j = lin->size; j > 0; j--, col++) + sum -= col->data * x.Get(col->colnr); + + res.Set (i, sum); + } + } + else + { + res = b; + for (i = 1; i <= n; i++) + { + lin = &lins.Get(i); + sum = 0; + col = lin->col; + xi = x.Get(i); + + for (j = lin->size; j > 0; j--, col++) + { + sum -= col->data * x.Get(col->colnr); + if (col->colnr != i) + res.Elem(col->colnr) -= col->data * xi; + } + + res.Elem(i) += sum; + } + } + */ + } + + +void SparseMatrix :: ResiduumTrans (const BaseVector & /* bx */, + const BaseVector & /* bb */, + BaseVector & /* bres */) const + { + cerr << "SparseMastrix :: Residuumtrans called, but not implemented" << endl; + + /* + INDEX i, j, n; + colstruct * col; + const linestruct * lin; + const Vector & x = bx.CastToVector(); + const Vector & b = bb.CastToVector(); + Vector & res = bres.CastToVector(); + + + res.SetLength (Width()); + + if (res.Length() != b.Length() || b.Length() != Width() || + x.Length() != Height()) + { + (*myerr) << "SparseMatrix::ResiduumTrans: Dimensions don't fit" << endl; + return; + } + + if (!Symmetric()) + { + n = Height(); + + res = b; + + for (i = 1; i <= n; i++) + { + lin = &lins.Get(i); + col = lin->col; + + for (j = lin->size; j > 0; j--, col++) + res.Elem(col->colnr) -= col->data * x.Get(i); + } + } + else + { + Residuum (bx, bb, bres); + } + */ + } + + + +ostream & SparseMatrix :: Print (ostream & s) const + { + INDEX i, j; + + if (Symmetric()) s << "Lower half of matrix:" << endl; + + for (i = 1; i <= Height(); i++) + { + s << "Line " << i << " "; + + if (Symmetric()) + { + for (j = 1 ; j <= GetDiagPos (i); j++) + s << "(" << GetColIndex (i, j) << ": " << GetData (i, j) << ") "; + } + else + { + for (j = 1 ; j <= ElementsInLine (i); j++) + s << "(" << GetColIndex (i, j) << ": " << GetData (i, j) << ") "; + } + + s << endl; + } + return s; + } + + + + + + +void SparseMatrix :: AddElementMatrix (const ARRAY<INDEX> & pnum, + const BaseMatrix & elemmat) +{ + int i, j, i1, i2, n; + + n = pnum.Size(); + static ARRAY<int> spnum, map; + spnum.SetSize (n); + map.SetSize (n); + + for (i = 1; i <= n; i++) + spnum.Elem(i) = pnum.Get(i); + + for (i = 1; i <= n; i++) + for (j = 1; j <= n-1; j++) + if (spnum.Elem(j) > spnum.Elem(j+1)) + swap (spnum.Elem(j), spnum.Elem(j+1)); + + for (i = 1; i <= n; i++) + for (j = 1; j <= n; j++) + if (pnum.Get(i) == spnum.Get(j)) + map.Elem(j) = i; + + + const DenseMatrix & delemmat = (const DenseMatrix&)elemmat; + if (Symmetric()) + { + for (i1 = 1; i1 <= n; i1++) + { + INDEX ii1 = spnum.Get(i1); + const INDEX * coli = graph->lines.Get(ii1).col; + double * val = data.Get(ii1); + int ncol = graph->lines.Get(ii1).size; + + int hi = 0; + for (i2 = 1; i2 <= i1; i2++) + { + while (coli[hi] < spnum.Get(i2)) + hi++; + val[hi] += delemmat.Get(map.Get(i1), map.Get(i2)); + } + } + + /* + for (i1 = 1; i1 <= pnum.Size(); i1++) + for (i2 = 1; i2 <= i1; i2++) + Elem(pnum.Get(i1), pnum.Get(i2)) += delemmat.Get(i1, i2); + */ + } + else + { + for (i1 = 1; i1 <= n; i1++) + { + INDEX ii1 = spnum.Get(i1); + const INDEX * coli = graph->lines.Get(ii1).col; + double * val = data.Get(ii1); + int ncol = graph->lines.Get(ii1).size; + + int hi = 0; + for (i2 = 1; i2 <= n; i2++) + { + while (coli[hi] < spnum.Get(i2)) + hi++; + val[hi] += delemmat.Get(map.Get(i1), map.Get(i2)); + } + } + + /* + for (i1 = 1; i1 <= pnum.Size(); i1++) + for (i2 = 1; i2 <= pnum.Size(); i2++) + Elem(pnum.Get(i1), pnum.Get(i2)) += delemmat.Get(i1, i2); + */ + } +} + + + + +double SparseMatrix :: RowTimesVector (INDEX i, const Vector & v) const + { + const double * valp; + const INDEX * col; + int coln; + double sum; + int j; + + /* + if (Width() > v.Length()) + { + cerr << "SparseMatrix::RowTimesVector: Size doesn't fit" << endl; + return 0; + } + */ + + col = graph->lines.Get(i).col; + valp = data.Get(i); + sum = 0; + coln = Symmetric() ? graph->lines.Get(i).diag : graph->lines.Get(i).size; + + for (j = 1; j <= coln; ++j, ++col, ++valp) + sum += (*valp) * v.Get(*col); + + return sum; + + /* + col = graph->lines.Get(i).col; + valp = data.Get(i); + coln = graph->lines.Get(i).size; + val = v.Get(i); + + // lin = &lins.Get(i); + // col = lin->col; + // val = v.Get(i); + + for (j = 1; j <= coln; j++, col++, valp++) + prod.Elem(*col) += (*valp) * val; + */ + + + } + + + +void SparseMatrix :: AddRowToVector (INDEX i, double s, Vector & v) const +{ + const double * valp; + const INDEX * col; + double * vp; + int coln, j; + +#ifdef debug + if (Width() > v.Length()) + { + cerr << "SparseMatrix::AddRowToVector: Size doesn't fit" + << "w = " << Width() << " len = " << v.Length() << endl; + return; + } +#endif + + vp = &v.Elem(1) - 1; + valp = data.Get(i); + col = graph->lines.Get(i).col; + coln = Symmetric() ? graph->lines.Get(i).diag : graph->lines.Get(i).size; + + // for (j = 0; j < coln; j++) + // vp[col[j]] += s * valp[j]; + + for (j = coln-1; j >= 0; --j, ++valp, ++col) + vp[*col] += s * (*valp); +} + + + + + + +char SparseMatrix :: Used (INDEX i, INDEX j) const + { + return (graph->GetPosition(i, j) != 0); + } + + + +double SparseMatrix :: Get(INDEX i, INDEX j) const + { + if (Symmetric() && (j > i)) swap (i, j); + + int pos = graph->GetPosition(i, j); + if (pos) + return data.Get(i)[pos-1]; + else + return 0; + } + + +/* + quick search: + + const colstruct * col = lins.Get(i).col; + INDEX max = lins.Get(i).size; + + int l = 0, k = 1, newind; + + while (k < max) + k <<= 1; + + + while (k > 0) + { + k >>= 1; + newind = k+l; + if (newind >= max) continue; + if (col[newind].colnr <= j) + l += k; + } + + if (l < max && col[l].colnr == j) return col[l].data; + + return 0; + */ + + + +void SparseMatrix :: Set(INDEX i, INDEX j, double v) + { + Elem (i, j) = v; + } + + + +double & SparseMatrix :: Elem(INDEX i, INDEX j) + { + if (Symmetric() && j > i) swap (i, j); + + int pos = graph->GetPosition (i, j); + if (!pos) + { + CreatePosition (i, j); + pos = graph->GetPosition (i, j); + } + + return data.Elem(i)[pos-1]; + } + + + + + + + + +SparseMatrixFlex :: SparseMatrixFlex (INDEX h, INDEX w) + : SparseMatrix (h, w) +{ + INDEX i; + graph = + mygraph = new MatrixGraph (h); + + data.SetSize (h); + for (i = 1; i <= graph->Size(); i++) + { + data.Elem(i) = new double[graph->lines.Get(i).allocsize]; + data.Elem(i)[0] = 0; + } +} + +SparseMatrixFlex :: ~SparseMatrixFlex () +{ + ; +} + + +void SparseMatrixFlex :: SetSize (INDEX /* h */, INDEX /* w */) +{ + cerr << "SparseMatrixFlex :: SetSize() not implemented" << endl; +} + +void SparseMatrixFlex :: SetSymmetric (int sym) +{ + BaseMatrix::SetSymmetric (sym); +} + +void SparseMatrixFlex :: ChangeSize (INDEX /* h */, INDEX /* w */) +{ + cerr << "SparseMatrixFlex :: ChangeSize() not implemented" << endl; +} + + +void SparseMatrixFlex :: DeleteElements () +{ + ; +} + +BaseMatrix * SparseMatrixFlex :: Copy () const +{ + return (SparseMatrixFlex*)this; +} + + +int SparseMatrixFlex :: CreatePosition (INDEX i, INDEX j) +{ + int oldlinesize = graph->lines.Get(i).allocsize; + if (mygraph->CreatePosition(i, j)) + { + int newlinesize = graph->lines.Get(i).allocsize; + if (oldlinesize != newlinesize) + { + double * hdp = new double[newlinesize]; + memcpy (hdp, data.Elem(i), sizeof(double) * oldlinesize); + delete data.Elem(i); + data.Elem(i) = hdp; + } + + int pos = graph->GetPosition (i, j); + int size = graph->lines.Get(i).size; + + memmove (&data.Elem(i)[pos], &data.Elem(i)[pos-1], + sizeof(double) * (size-pos)); + data.Elem(i)[pos-1] = 0; + } + + return 0; +} + + + + +SparseMatrixFix :: SparseMatrixFix (const MatrixGraph & agraph, + int asymmetric) + : SparseMatrix (agraph.Size()) +{ + graph = &agraph; + SetSymmetric (asymmetric); + + data.SetSize (graph->Size()); + + int i, nne; + double * block; + + nne = 0; + for (i = 1; i <= graph->Size(); i++) + { + if (Symmetric()) + nne += graph->lines.Get(i).diag; + else + nne += graph->lines.Get(i).size; + } + + block = new double[nne]; + + for (i = 0; i < nne; i++) + block[i] = 0; + + nne = 0; + for (i = 1; i <= graph->Size(); i++) + { + data.Elem(i) = &block[nne]; + if (Symmetric()) + nne += graph->lines.Get(i).diag; + else + nne += graph->lines.Get(i).size; + } + +} + + +SparseMatrixFix :: ~SparseMatrixFix () +{ + ; +} + +int SparseMatrixFix :: CreatePosition (INDEX i, INDEX j) +{ + (*myerr) << "SparseMatrixFix cannot change graph, requested: " + << i << "-" << j << endl; + return 0; +} + +#ifdef nothing + + +SparseMatrix :: SparseMatrix () : BaseMatrix (), lins() + { + }; + +SparseMatrix :: SparseMatrix (INDEX h, INDEX w) : BaseMatrix (h, w), lins (h) + { + if (!w) w = h; + + for (INDEX i = 1; i <= h; i++) + { + lins[i].size = 0; + lins[i].maxsize = 0; + lins[i].col = NULL; + } + } + +SparseMatrix :: SparseMatrix (const SparseMatrix & m2) : BaseMatrix(), lins() + { + (*this) = m2; + } + + +SparseMatrix :: ~SparseMatrix () + { + DeleteElements (); + } + + + +void SparseMatrix :: SetSize (INDEX h, INDEX w) + { + if (!w) w = h; + DeleteElements (); + + if (height == h && width == w) return; + + height = h; + width = w; + lins.SetSize (height); + + if (lins.Size () == height) + { + for (INDEX i = 1; i <= h; i++) + { + lins[i].size = 0; + lins[i].maxsize = 0; + lins[i].col = NULL; + } + } + else + { + height = width = 0; + (*myerr) << "SparseMatrix::SetSize: Out of memory" << endl; + } + } + + +void SparseMatrix :: ChangeSize (INDEX h, INDEX w) + { + INDEX i; + + if (!w) w = h; + if (height == h && width == w) return; + + lins.SetSize (h); + + if (lins.Size () == h) + { + for (i = height+1; i <= h; i++) + { + lins[i].size = 0; + lins[i].maxsize = 0; + lins[i].col = NULL; + } + for (i = h+1; i <= height; i++) + { + if (lins[i].col) + { + DeleteColStruct (lins[i].col, lins[i].maxsize); + + lins[i].col = NULL; + lins[i].size = 0; + lins[i].maxsize = 0; + } + } + + height = h; + width = w; + } + else + { + height = width = 0; + (*myerr) << "SparseMatrix::SetSize: Out of memory" << endl; + } + } + + +void SparseMatrix :: SetSymmetric (int sym) + { + INDEX i, j; + int nr; + + if (sym != Symmetric()) + { + BaseMatrix :: SetSymmetric (sym); + + if (!sym) + { + for (i = 1; i <= Height(); i++) + for (nr = 1; nr <= ElementsInLine (i); nr++) + { + j = GetIndex (i, nr); + if (j < i) + Elem (j, i) = GetData (i, nr); + } + } + else + { + DeleteElements(); + } + } + } + + +void SparseMatrix :: DeleteElements () + { + for (INDEX i = 1; i <= lins.Size(); i++) + { + if (lins[i].col) + { + DeleteColStruct (lins[i].col, lins[i].maxsize); + + lins[i].col = NULL; + lins[i].size = 0; + lins[i].maxsize = 0; + } + } + } + + + +double & SparseMatrix::operator() (INDEX i, INDEX j) +{ + if (i >= 1 && j >= 1 && i <= height && j <= width) + { + return Elem(i, j); + } + else (*myerr) << "\nindex (" << i << "," << j << ") out of range (1.." + << height << ",1.." << width << ")\n"; + return shit; +} + +double SparseMatrix::operator() (INDEX i, INDEX j) const +{ + if (i >= 1 && j >= 1 && i <= height && j <= width) + { + return Get(i, j); + } + else (*myerr) << "\nindex (" << i << "," << j << ") out of range (1.." + << height << ",1.." << width << ")\n"; + return 0; +} + +SparseMatrix & SparseMatrix :: operator= (const SparseMatrix & m2) + { + INDEX i, j; + + SetSize (m2.Height(), m2.Width()); + SetSymmetric (m2.Symmetric()); + + for (i = 1; i <= m2.Height(); i++) + for (j = 1; j <= m2.ElementsInLine(i); j++) + (*this).Elem(i, m2.GetIndex(i, j)) = m2.GetData(i, j); + return *this; + } + + +SparseMatrix & SparseMatrix :: operator*= (double v) + { + INDEX i, j; + + for (i = 1; i <= Height(); i++) + for (j = 1; j <= ElementsInLine(i); j++) + GetDataRef(i, j) *= v; + return *this; + } + + + +char SparseMatrix :: Used (INDEX i, INDEX j) const + { + if (Symmetric() && j > i) swap (i, j); + + if (i < 1 || i > height) return 0; + + const colstruct * col = lins.Get(i).col; + INDEX max = lins.Get(i).size; + + for (int k = 0; k < max; k++, col++) + if (col->colnr == j) return 1; + + return 0; + } + + + +double SparseMatrix :: Get(INDEX i, INDEX j) const + { + if (Symmetric() && j > i) swap (i, j); + + const colstruct * col = lins.Get(i).col; + INDEX max = lins.Get(i).size; + + int l = 0, k = 1, newind; + + while (k < max) + k <<= 1; + + + while (k > 0) + { + k >>= 1; + newind = k+l; + if (newind >= max) continue; + if (col[newind].colnr <= j) + l += k; + } + + if (l < max && col[l].colnr == j) return col[l].data; + + return 0; + + /* + for (INDEX k = 0; k < max; k++, col++) + if (col->colnr == j) + { + if (l != k) cerr << "Set: ind not ok" << endl; + else cerr << "is ok" << endl; + return col->data; + } + + return 0; + */ + } + + +void SparseMatrix :: Set(INDEX i, INDEX j, double v) + { + Elem (i, j) = v; + } + + + +double & SparseMatrix :: Elem(INDEX i, INDEX j) + { + if (Symmetric() && j > i) swap (i, j); + + linestruct * lin = &lins.Elem(i); + colstruct * col, *ncol; + + int size = lin->size; + int pos; + + if (size) + { + + // bereits Elemente in der Liste + + if (j > lin->col[size-1].colnr) + { + + // neues Element an letzter Position einfuegen + + if (lin->maxsize > size) + { + lin->size++; + lin->col[size].colnr = j; + return lin->col[size].data = 0; + } + + if ( (ncol = NewColStruct(lin->maxsize+4)/* new colstruct[lin->maxsize+4] */) != NULL) + { + memcpy (ncol, lin->col, sizeof(colstruct) * size); + + DeleteColStruct (lin->col, lin->maxsize); + + lin->maxsize += 4; + lin->col = ncol; + lin->size++; + ncol[size].colnr = j; + return ncol[size].data = 0; + } + else + { + (*myerr) << "SparseMatrix::Elem: Out of memory 1" << endl; + return shit; + } + + } + else + { + + for (col = lin->col; col->colnr < j; col++); + // Zeilenliste durchsuchen + + if (col->colnr == j) return col->data; + // Element exisitiert bereits + + if (lin->maxsize > size) + { + memmove (col+1, col, size_t((char*)&lin->col[size] - (char*)col)); + + lin->size++; + col->colnr = j; + return col->data = 0; + } + + pos = size_t (col - lin->col); + + if ( (ncol = NewColStruct(lin->maxsize+4) ) != NULL) + { + + if (pos) memcpy (ncol, lin->col, sizeof(colstruct) * pos); + memcpy (ncol+(pos+1), col, sizeof(colstruct) * (size-pos)); + + DeleteColStruct (lin->col, lin->maxsize); +// delete lin->col; + + lin->maxsize += 4; + lin->col = ncol; + lin->size++; + ncol[pos].colnr = j; + return ncol[pos].data = 0; + } + else + { + (*myerr) << "SparseMatrix::Elem: Out of memory 2" << endl; + return shit; + } + } + } + else + { + // kein Element in der Liste + + if (lin->maxsize) + { + // Liste bereits angelegt + + lin->size = 1; + lin->col->colnr = j; + return lin->col->data = 0; + } + else + { + if ( (lin->col = NewColStruct(6) ) != NULL ) + { + lin->maxsize = 6; + lin->size = 1; + lin->col->colnr = j; + return lin->col->data = 0; + } + else + { + (*myerr) << "SparseMatrix::Elem: Out of memory 3" << endl; + return shit; + } + } + } + } + + + +void SparseMatrix :: Delete (INDEX i, int nr) + { + colstruct * col = lins[i].col; + + nr--; + while (nr < lins[i].size-1) + { + col[nr].data = col[nr+1].data; + col[nr].colnr = col[nr+1].colnr; + nr++; + } + lins[i].size--; + } + +void SparseMatrix :: DeleteElem (INDEX i, INDEX j) + { + int nr; + int dec = 0; + + if (Symmetric() && j > i) swap (i, j); + + colstruct * col = lins[i].col; + + for (nr = 0; nr < lins[i].size; nr++) + { + if (dec) + { + col[nr-1].data = col[nr].data; + col[nr-1].colnr = col[nr].colnr; + } + if (col[nr].colnr == j) dec = 1; + } + if (dec) + lins[i].size--; + } + + +void SparseMatrix :: SetLineAllocSize (INDEX i, int j) + { + colstruct * ncol; + + + if (lins[i].maxsize < j) + { + if ( (ncol = NewColStruct(j)) != NULL) + { + memcpy (ncol, lins[i].col, sizeof(colstruct) * lins[i].size); + + if (lins[i].maxsize) + DeleteColStruct (lins[i].col, lins[i].maxsize); + + lins[i].maxsize = j; + lins[i].col = ncol; + } + else + (*myerr) << "SPARSE_MATIRX :: SetLineAllocSize: Out of Memory" << endl; + } + } + + + + + + + + + + + + + + +SparseMatrix operator* (const SparseMatrix & m1, + const SparseMatrix & m2) + { + SparseMatrix m(m1.Height(), m2.Width()); + INDEX i, j, k, nr; + + if (!m1.Symmetric() && !m2.Symmetric()) + { + for (i = 1; i <= m1.Height(); i++) + { + for (j = 1; j <= m1.ElementsInLine(i); j++) + { + nr = m1.GetIndex (i, j); + for (k = 1; k <= m2.ElementsInLine(nr); k++) + { + m(i, m2.GetIndex(nr, k)) += m1.GetData(i, j) * m2.GetData(nr, k); + } + } + } + } + else + { + (*myerr) << "SparseMatrix :: operator* not implemented for symmetric case" << endl; + } + return m; + } + + +SparseMatrix & SparseMatrix :: operator+= (const SparseMatrix & m2) + { + INDEX i, k; + int j; + + if (Symmetric() == m2.Symmetric()) + { + for (i = 1; i <= Height(); i++) + for (j = 1; j <= m2.ElementsInLine (i); j++) + { + k = m2.GetIndex (i, j); + Elem(i, k) += m2.GetData (i, j); + } + } + else + { + (*myerr) << "SparseMatrix :: operator+= not implemented for different cases" << endl; + } + return *this; + } + + + +SparseMatrix & SparseMatrix :: operator*= (const SparseMatrix & m2) + { + INDEX i, k; + int j, l; + colstruct * cs; + int ms, s; + + if (!Symmetric() && !m2.Symmetric()) + { + for (i = 1; i <= Height(); i++) + { + cs = lins[i].col; + s = lins[i].size; + ms = lins[i].maxsize; + + lins[i].col = NULL; + lins[i].size = 0; + lins[i].maxsize = 0; + + + for (j = 0; j < s; j++) + { + k = cs[j].colnr; + + for (l = 1; l <= m2.ElementsInLine (k); l++) + Elem(i, m2.GetIndex(k, l)) += cs[j].data * m2.GetData(k, l); + } + + DeleteColStruct (cs, ms); + } + } + else + { + (*myerr) << "SparseMatrix :: operator*= not implemented for Symmetric matrices" << endl; + } + + return *this; + } + + +void SparseMatrix :: Solve (const Vector & v, Vector & sol) const + { + SparseMatrix temp = *this; + INDEX i, j, nr, k; + double q; + + sol = v; + + + if (!Symmetric()) + { + for (i = 1; i <= Height(); i++) + { + if (temp.ElementsInLine(i) < 1 || temp.GetIndex(i, 1) != i) + { + (*myerr) << "i = " << i << endl; + (*myerr) << "Solve: Matrix singular" << endl; + char ch; + cin >> ch; + } + for (j = 2; j <= temp.ElementsInLine(i); j++) + { + nr = temp.GetIndex(i, j); + if (temp.GetIndex(nr, 1) != i) + { + (*myerr) << temp << endl; + (*myerr) << "i = " << i << "j = " << j << "nr = " << nr << endl; + (*myerr) << "Solve: Graph not symmetrix" << endl; + char ch; + cin >> ch; + } + + q = temp.GetData (nr, 1) / temp.GetData(i, 1); + temp.Delete (nr, 1); + + for (k = 2; k <= temp.ElementsInLine (i); k++) + temp.Elem(nr, temp.GetIndex(i, k)) -= q * temp.GetData(i, k); + + sol(nr) -= q * sol(i); + } + } + + for (i = temp.Height(); i >= 1; i--) + { + for (j = 2; j <= temp.ElementsInLine(i); j++) + { + sol(i) -= temp.GetData(i, j) * sol(temp.GetIndex(i, j)); + } + sol(i) /= temp.GetData(i, 1); + } + } + else + (*myerr) << "SparseMatrix :: Solve not implemented for symmetic case" << endl; + } + + + + + +void Transpose (const SparseMatrix & m1, SparseMatrix & m2) + { + INDEX i, j; + + m2.SetSize(m1.Width(), m1.Height()); + m2.SetSymmetric(m1.Symmetric()); + + if (!m1.Symmetric()) + { + for (i = 1; i <= m1.Height(); i++) + for (j = 1; j <= m1.ElementsInLine(i); j++) + m2(m1.GetIndex(i, j), i) = m1.GetData(i, j); + } + else + m2 = m1; + } + + + +BaseMatrix * SparseMatrix :: Copy () const + { + return new SparseMatrix (*this); + } + + + + + + + +void SparseMatrix :: AddRowMatrix (INDEX row, const SparseMatrix & m2) + { + int i1, i2, i; + colstruct * cs1, * cs2, * ncs; + int s1, s2, s; + + s1 = lins[row].size; + s2 = m2.lins[1].size; + cs1 = lins[row].col; + cs2 = m2.lins[1].col; + + i1 = 0; + i2 = 0; + i = 0; + + + if (Symmetric()) + { + while (s2 && cs2[s2-1].colnr > row) s2--; + } + + + while (i1 < s1 && i2 < s2) + { + if (cs1[i1].colnr < cs2[i2].colnr) i1++; + else if (cs1[i1].colnr > cs2[i2].colnr) i2++; + else { i1++; i2++; } + i++; + } + + i += (s1 - i1); + i += (s2 - i2); + + s = i; + + if (s > s1) + { + ncs = NewColStruct (s); + + i1 = 0; + i2 = 0; + i = 0; + + while (i1 < s1 && i2 < s2) + { + if (cs1[i1].colnr < cs2[i2].colnr) + { + ncs[i].colnr = cs1[i1].colnr; + ncs[i].data = cs1[i1].data; + i1++; + } + else if (cs1[i1].colnr > cs2[i2].colnr) + { + ncs[i].colnr = cs2[i2].colnr; + ncs[i].data = cs2[i2].data; + i2++; + } + else + { + ncs[i].colnr = cs1[i1].colnr; + ncs[i].data = cs1[i1].data + cs2[i2].data; + i1++; + i2++; + } + i++; + } + + while (i1 < s1) + { + ncs[i].colnr = cs1[i1].colnr; + ncs[i].data = cs1[i1].data; + i1++; + i++; + } + + while (i2 < s2) + { + ncs[i].colnr = cs2[i2].colnr; + ncs[i].data = cs2[i2].data; + i2++; + i++; + } + + if (lins[row].maxsize) + DeleteColStruct (cs1, lins[row].maxsize); + + lins[row].col = ncs; + lins[row].size = s; + lins[row].maxsize = s; + } + + + else + { + i1 = 0; + i2 = 0; + + while (i2 < s2) + { + if (cs1[i1].colnr == cs2[i2].colnr) + { + cs1[i1].data += cs2[i2].data; + i2++; + } + i1++; + } + } + } + + +double SparseMatrix :: RowTimesVector (INDEX i, const Vector & v) const + { + const linestruct * lin; + const colstruct * col; + double sum; + int j; + + if (Width() > v.Length()) + { + cerr << "SparseMatrix::RowTimesVector: Size doesn't fit" << endl; + return 0; + } + + lin = &lins.Get(i); + sum = 0; + col = lin->col; + + for (j = lin->size; j > 0; j--, col++) + sum += col->data * v.Get(col->colnr); + + return sum; + } + +void SparseMatrix :: AddRowToVector (INDEX i, double s, Vector & v) const + { + const linestruct * lin; + const colstruct * col; + int j; + + if (Width() > v.Length()) + { + cerr << "SparseMatrix::AddRowToVector: Size doesn't fit" + << "w = " << Width() << " len = " << v.Length() << endl; + return; + } + + lin = &lins.Get(i); + col = lin->col; + + for (j = lin->size; j > 0; j--, col++) + v.Elem(col->colnr) += s * col->data; + } + + +static ARRAY<void*> poolarray; +static ARRAY<int> poolsizes; + + +SparseMatrix::colstruct * SparseMatrix :: NewColStruct (int s) + { +// return new colstruct[s]; + + + int i, j; + void * p; + colstruct * cs; + + if (s > 20) return new colstruct[s]; + + for (i = 1; i <= poolsizes.Size(); i++) + if (poolsizes.Get(i) == s) break; + + if (i > poolsizes.Size()) + { + poolsizes.Append(s); + poolarray.Append((void*)NULL); + i = poolsizes.Size(); + } + + p = poolarray.Get(i); + if (!p) + { + poolarray.Elem(i) = p = cs = new colstruct[10 * s]; + for (j = 0; j < 9; j++) + *(void**)(void*)(&cs[s * j]) = &cs[s * (j+1)]; + *(void**)(void*)(&cs[s * 9]) = NULL; + } + + poolarray.Elem(i) = *(void**)p; + return (colstruct*)p; + } + +void SparseMatrix :: DeleteColStruct (colstruct * cs, int s) + { +// delete cs; +// return; + + int i; + + if (s > 20) + { + delete cs; + return; + } + + for (i = 1; i <= poolsizes.Size(); i++) + if (poolsizes.Get(i) == s) break; + + + if (i > poolsizes.Size()) + { + (*myerr) << "SparseMatrix :: DeleteColStruct: Size not found" << endl; + return; + } + + + *(void**)(void*)cs = poolarray.Get(i); + poolarray.Elem(i) = cs; + } + +void SparseMatrix :: SetGraph (const class TABLE<INDEX> & graph) + { + int i, j, es, ad, nne; + colstruct * block; + + nne = 0; + for (i = 1; i <= graph.Size(); i++) + { + if (Symmetric()) + { + es = 0; + for (j = 1; j <= graph.EntrySize(i); j++) + if (graph.Get(i, j) <= i) + es++; + } + else + es = graph.EntrySize(i); + nne += es; + } + + oneblock = 1; + block = new colstruct[nne]; + + ad = 0; + for (i = 1; i <= graph.Size(); i++) + { + if (Symmetric()) + { + es = 0; + for (j = 1; j <= graph.EntrySize(i); j++) + if (graph.Get(i, j) <= i) + es++; + } + else + es = graph.EntrySize(i); + + lins.Elem(i).size = 0; + lins.Elem(i).maxsize = es; + lins.Elem(i).col = &block[ad]; + ad += es; + } + } + + + + +#endif +} diff --git a/Netgen/libsrc/linalg/sparsmat.hpp b/Netgen/libsrc/linalg/sparsmat.hpp new file mode 100644 index 0000000000..884ab6575c --- /dev/null +++ b/Netgen/libsrc/linalg/sparsmat.hpp @@ -0,0 +1,261 @@ +#ifndef FILE_SPARSMAT +#define FILE_SPARSMAT + +/* *************************************************************************/ +/* File: sparsmat.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Oct. 94 */ +/* *************************************************************************/ + + +class SparseMatrix; + +/** + The graph of a sparse matrix. + The graph is stored for a non-symmetric matrix +*/ +class MatrixGraph +{ + /// data structure for one row of matrix + struct linestruct + { + /// allocated size + int allocsize; + /// used size + int size; + /// diag element (always allocated) + int diag; + /// colume numbers + INDEX* col; + }; + + /// graph of matrix + ARRAY<linestruct> lines; + /// increment of allocated line-memory on overflow + int increment; + +public: + //@{ @name Constructors, Destructor + + /// Height of matrix, increment value for line-overflow + MatrixGraph (int size, int aincrement = 5); + /// Allocates graph with elements per row given in ARRAY linesize + MatrixGraph (const ARRAY<int> & linesize); + //@} + + + /// returns position of Element (i, j), 0 for unused + int GetPosition (INDEX i, INDEX j) const; + + /// returns position of new element + int CreatePosition (INDEX i, INDEX j); + + /// Returns height of matrix + int Size() const { return lines.Size(); } + + + friend class SparseMatrix; + friend class SparseMatrixFlex; + friend class SparseMatrixFix; + friend class PointJacobiPrecond; +}; + + + + + + +/** + Base class for sparse matrix. + Matrix to work with in most applications + */ +class SparseMatrix : public BaseMatrix +{ +protected: + /// graph of matrix + const MatrixGraph * graph; + /// pointer to matrix values in each row + ARRAY<double*> data; + +public: + + /// returns reference, fail save but slow + virtual double & operator() (INDEX i, INDEX j); + /// returns value, fail save but slow + virtual double operator() (INDEX i, INDEX j) const; + + + /// prod = matrix x v + virtual void Mult (const BaseVector & v, BaseVector & prod) const; + /// prod = matrix^T x v + virtual void MultTrans (const BaseVector & v, BaseVector & prod) const; + /// res = b - mat x x + virtual void Residuum (const BaseVector & x, const BaseVector & b, + BaseVector & res) const; + /// res = b - mat^T x x + virtual void ResiduumTrans (const BaseVector & x, const BaseVector & b, + BaseVector & res) const; + + + /** + Add element matrix to sparse matrix. + The graph of the element-matrix must be symmetric. + Global point numbers are given in pnum. + */ + virtual void AddElementMatrix (const ARRAY<INDEX> & pnum, const BaseMatrix & elemmat); + + /// for multigrid-extension, should be removed from here + void GSStepToInner (const Vector & b, Vector & x, double dump, + const BitArray & inner) const; + + /// for multigrid-extension, should be removed from here + void GSStepBackToInner (const Vector & b, Vector & x, double dump, + const BitArray & inner) const; + + /// + virtual ostream & Print (ostream & s) const; + + /** Scalar product of i-th row times vector. + For symmetric matrices only lower left block + (including diagonal) is used. + */ + double RowTimesVector (INDEX i, const Vector & v) const; + /** Adds s times the i-th row of matrix to vector v. + For symmetric matrices only lower left block + (including diagonal) is used. + */ + void AddRowToVector (INDEX i, double s, Vector & v) const; + + /** Number of elements in line. + For symmetric matrices GetDiagPos must be used for + most purposes. + */ + int ElementsInLine (INDEX i) const + { return graph->lines.Get(i).size; } + + /** Columne index of nr-th non-zero element in row i */ + INDEX GetColIndex (INDEX i, int nr) const + { return graph->lines.Get(i).col[nr-1]; } + + /** Referece to columne index of nr-th non-zero + element in row i */ + const INDEX & GetColIndexRef (INDEX i, int nr) const + { return graph->lines.Get(i).col[nr-1]; } + + /** Value of nr-th non-zero element in row i */ + double GetData (INDEX i, int nr) const + { return data.Get(i)[nr-1]; } + + /** Reference to value of nr-th non-zero element in row i */ + const double & GetDataRef (INDEX i, int nr) const + { return data.Get(i)[nr-1]; } + + /** Returns value of diagonal element in row i */ + double GetDiag (INDEX i) const + { return data.Get(i)[graph->lines.Get(i).diag-1]; } + + /** Which position has diagonal element in row i ? */ + int GetDiagPos (INDEX i) const + { return graph->lines.Get(i).diag; } + + /** Returns matrix value of row i, col j. + For symmetric matrices the indices will be sorted in + this function */ + double Get(INDEX i, INDEX j) const; + + /** Set value of element (i, j) to v. + For symmetric matrices element (j, i) is set. */ + void Set(INDEX i, INDEX j, double v); + + /** Returns reference to element (i, j). + For symmetric matrices a reference to (j, i) is returned */ + double & Elem(INDEX i, INDEX j); + + /** Is element (i, j) used ? */ + char Used (INDEX i, INDEX j) const; + +protected: + /// A sparse matrix must not be constructed + SparseMatrix (INDEX h, INDEX w = 0); + /// Allocates matrix position + virtual int CreatePosition (INDEX i, INDEX j) = 0; + +private: + /// + friend class ScalarBlockJacobiPrecond; + friend class PointJacobiPrecond; +}; + + + + +/** Sparse matrix with flexible graph. + On demand, a matrix position is allocated */ +class SparseMatrixFlex : public SparseMatrix +{ + /// non-const pointer to graph. + MatrixGraph * mygraph; + +public: + /// + SparseMatrixFlex (); + /// + SparseMatrixFlex (INDEX h, INDEX w = 0); + /// + SparseMatrixFlex (const SparseMatrix & m2); + /// + virtual ~SparseMatrixFlex (); + + /// + virtual void SetSize (INDEX h, INDEX w = 0); + /// + virtual void SetSymmetric (int sym = 1); + /// + virtual void ChangeSize (INDEX h, INDEX w = 0); + /// + void DeleteElements (); + + + /// + SparseMatrix & operator= (const SparseMatrix & m2); + /// + SparseMatrix & operator*= (double v); + + + /// + virtual BaseMatrix * Copy () const; + /// + void Delete (INDEX i, int nr); + /// + void DeleteElem (INDEX i, INDEX j); + + /// + void SetLineAllocSize (INDEX i, int j); + +protected: + /// + virtual int CreatePosition (INDEX i, INDEX j); + +}; + + + + +/** Sparse matrix with fixed graph. + After construction of the matrix, the graph + must not be changed. */ +class SparseMatrixFix : public SparseMatrix +{ +public: + /// + SparseMatrixFix (const MatrixGraph & agraph, int asymmetric = 0); + /// + virtual ~SparseMatrixFix (); + +protected: + /// CreatePosition is not allowed for SparseMatrixFix -> error + virtual int CreatePosition (INDEX i, INDEX j); +}; + + +#endif diff --git a/Netgen/libsrc/linalg/vector.cpp b/Netgen/libsrc/linalg/vector.cpp new file mode 100644 index 0000000000..47be4eefd9 --- /dev/null +++ b/Netgen/libsrc/linalg/vector.cpp @@ -0,0 +1,786 @@ +#ifdef abc +#include <mystdlib.h> +#include <linalg.hpp> + +namespace netgen +{ + +double BaseVector :: shit = 0; + +// %FD Constructs a vector of length zero +BaseVector :: BaseVector () + { + length = 0; + } + +// %FD Constructs a vector of given length +BaseVector :: BaseVector ( + INDEX alength // length of the vector + ) + { + length = alength; + } + +// %FD Sets length of the vector, old vector will be destroyed +void +BaseVector :: SetLength ( + INDEX alength // new length of the vector + ) + { + length = alength; + } + +// %FD Changes length of the vector, old values stay valid +void +BaseVector :: ChangeLength ( + INDEX alength // new length of the vector + ) + { + length = alength; + } + + + +// %FD { Write a vector with the help of the '<<' operator onto a stream } +ostream & // stream for further use +operator<< ( + ostream & s, // stream to write vector onto + const BaseVector & v // vector to write + ) + { + return v.Print (s); + } + + +// %FD{ Divides every component of the vector by the scalar c. +// The function checks for division by zero } +BaseVector & // result vector +BaseVector :: operator/= ( + double c // scalar to divide by + ) + { + if (c) + return (*this) *= (1/c); + else + { + (*myerr) << "operator/=: division by zero" << endl; + return *this; + } + } + + +// %FD Creates a copy of the object +BaseVector * // pointer to the new vector +BaseVector :: Copy () const + { + cerr << "Base_vector::Copy called" << endl << flush; + return NULL; + } + + + + +void BaseVector :: GetElementVector (const ARRAY<INDEX> & pnum, + BaseVector & elvec) const +{ + int i; + for (i = 1; i <= pnum.Size(); i++) + elvec(i) = (*this)(pnum.Get(i)); +} + +void BaseVector :: SetElementVector (const ARRAY<INDEX> & pnum, + const BaseVector & elvec) +{ + int i; + for (i = 1; i <= pnum.Size(); i++) + (*this)(pnum.Get(i)) = elvec(i); +} + + +void BaseVector :: AddElementVector (const ARRAY<INDEX> & pnum, + const BaseVector & elvec) +{ + int i; + for (i = 1; i <= pnum.Size(); i++) + (*this)(pnum.Get(i)) += elvec(i); +} + + + + + + + + + + + +TempVector :: ~TempVector () + { + delete vec; + } + +TempVector BaseVector :: operator+ (const BaseVector & v2) const + { + return (*Copy()) += v2; + } + +TempVector BaseVector :: operator- (const BaseVector & v2) const + { + return (*Copy()) -= v2; + } + +TempVector BaseVector :: operator- () const + { + return (*Copy()) *= -1; + } + + +TempVector operator* (const BaseVector & v1, double scal) + { + return (*v1.Copy()) *= scal; + } + +TempVector operator/ (const BaseVector & v1, double scal) + { + return (*v1.Copy()) /= scal; + } + + +TempVector operator* (double scal, const BaseVector & v1) + { + return v1 * scal; + } + + + + + +BaseVector * TempVector :: Copy () const + { + return vec->Copy(); + } + + + + + + + + + + +double Vector :: shit = 0; + +class clVecpool +{ +public: + ARRAY<double *> vecs; + ARRAY<INDEX> veclens; + + ~clVecpool(); +}; + +clVecpool :: ~clVecpool() +{ + int i; + for (i = 1; i <= vecs.Size(); i++) + delete vecs.Elem(i); +} + +static clVecpool vecpool; + + + +static double * NewDouble (INDEX len) +{ + if (len < 10) + return new double[len]; + else + { + int i; + for (i = 1; i <= vecpool.veclens.Size(); i++) + if (vecpool.veclens.Get(i) == len) + { + double * hvec = vecpool.vecs.Get(i); + vecpool.vecs.DeleteElement(i); + vecpool.veclens.DeleteElement(i); + return hvec; + } + + return new double[len]; + } +} + +static void DeleteDouble (INDEX len, double * dp) +{ + if (len < 10) + delete [] dp; + else + { + vecpool.vecs.Append (dp); + vecpool.veclens.Append (len); + } +} + + + +Vector :: Vector () : BaseVector() + { + data = NULL; + } + +Vector :: Vector (INDEX alength) : BaseVector (alength) + { + if (length) + { + // data = new double[length]; + data = NewDouble (length); + + if (!data) + { + length = 0; + (*myerr) << "Vector not allocated" << endl; + } + } + else + data = NULL; + } + + +Vector :: Vector (const Vector & v2) + { + length = v2.length; + + if (length) + { + // data = new double[length]; + data = NewDouble (length); + + if (data) + { + memcpy (data, v2.data, length * sizeof (double)); + } + else + { + length = 0; + (*myerr) << "Vector::Vector : Vector not allocated" << endl; + } + } + else + data = NULL; + } + + +Vector :: ~Vector () +{ + // veclenfile << "~Vector delete: " << length << endl; + if (data) + { + DeleteDouble (length, data); + // delete [] data; + } + +} + +void Vector :: SetLength (INDEX alength) + { + if (length == alength) return; + + if (data) + { + DeleteDouble (length, data); + // delete [] data; + } + data = NULL; + length = alength; + + if (length == 0) return; + // data = new double[length]; + data = NewDouble (length); + + if (!data) + { + length = 0; + (*myerr) << "Vector::SetLength: Vector not allocated" << endl; + } + } + +void Vector :: ChangeLength (INDEX alength) +{ + (*mycout) << "Vector::ChangeLength called" << endl; + if (length == alength) return; + + if (alength == 0) + { + // delete [] data; + DeleteDouble (length, data); + length = 0; + return; + } + + double * olddata = data; + + data = NewDouble (alength); + // data = new double[alength]; + if (!data) + { + length = 0; + (*myerr) << "Vector::SetLength: Vector not allocated" << endl; + delete [] olddata; + } + + memcpy (data, olddata, min2(alength, length)); + + delete [] olddata; + length = alength; + } + +/// NEW RM +void Vector::SetBlockLength (INDEX /* blength */) +{ + MyError("BaseVector::SetBlockLength was called for a Vector"); +} + + +double & Vector :: operator() (INDEX i) + { + if (i >= 1 && i <= length) return Elem(i); + else (*myerr) << "\nindex " << i << " out of range (" + << 1 << "," << Length() << ")\n"; + return shit; + } + +double Vector :: operator() (INDEX i) const + { + if (i >= 1 && i <= length) return Get(i); + else (*myerr) << "\nindex " << i << " out of range (" + << 1 << "," << Length() << ")\n" << flush; + return shit; + } + + + +double Vector :: SupNorm () const + { + double sup = 0; + + for (INDEX i = 1; i <= Length(); i++) + if (fabs (Get(i)) > sup) + sup = fabs(Get(i)); + + return sup; + } + +double Vector :: L2Norm () const + { + double sum = 0; + + for (INDEX i = 1; i <= Length(); i++) + sum += Get(i) * Get(i); + + return sqrt (sum); + } + +double Vector :: L1Norm () const + { + double sum = 0; + + for (INDEX i = 1; i <= Length(); i++) + sum += fabs (Get(i)); + + return sum; + } + +double Vector :: Max () const + { + if (!Length()) return 0; + double m = Get(1); + for (INDEX i = 2; i <= Length(); i++) + if (Get(i) > m) m = Get(i); + return m; + } + +double Vector :: Min () const + { + if (!Length()) return 0; + double m = Get(1); + for (INDEX i = 2; i <= Length(); i++) + if (Get(i) < m) m = Get(i); + return m; + } + + +/* +ostream & operator<<(ostream & s, const Vector & v) + { + int w = s.width(); + if (v.Length()) + { + s.width(0); + s << '('; + for (INDEX i = 1; i < v.Length(); i++) + { + s.width(w); + s << v.Get(i) << ","; + if (i % 8 == 0) s << endl << ' '; + } + s.width(w); + s << v.Get(v.Length()) << ')'; + } + else + s << "(Vector not allocated)"; + + return s; + } +*/ + +ostream & Vector :: Print (ostream & s) const + { + int w = s.width(); + if (Length()) + { + s.width(0); + s << '('; + for (INDEX i = 1; i < Length(); i++) + { + s.width(w); + s << Get(i) << ","; + if (i % 8 == 0) s << endl << ' '; + } + s.width(w); + s << Get(Length()) << ')'; + } + else + s << "(Vector not allocated)"; + + return s; + } + + + +BaseVector & Vector :: operator+= (const BaseVector & v2) + { + const Vector & hv2 = v2.CastToVector(); + + if (Length() == hv2.Length()) + for (INDEX i = 1; i <= Length(); i++) + Elem (i) += hv2.Get(i); + else + (*myerr) << "operator+= illegal dimension" << endl; + return *this; + } + +BaseVector & Vector :: operator-= (const BaseVector & v2) + { + const Vector & hv2 = v2.CastToVector(); + + if (Length() == hv2.Length()) + for (INDEX i = 1; i <= Length(); i++) + Elem (i) -= hv2.Get(i); + else + (*myerr) << "operator-= illegal dimension" << endl; + return *this; + } + +BaseVector & Vector :: operator*= (double c) + { + for (INDEX i = 1; i <= Length(); i++) + Elem(i) *= c; + return *this; + } + + + +BaseVector & Vector :: Add (double scal, const BaseVector & v2) + { + const Vector & hv2 = v2.CastToVector(); + + if (Length() == hv2.Length()) + { + double * p1 = data; + double * p2 = hv2.data; + + for (INDEX i = Length(); i > 0; i--) + { + (*p1) += scal * (*p2); + p1++; p2++; + } + } + else + (*myerr) << "Vector::Add: illegal dimension" << endl; + return *this; + } + +BaseVector & Vector :: Add2 (double scal, const BaseVector & v2, + double scal3, const BaseVector & v3) + { + const Vector & hv2 = v2.CastToVector(); + const Vector & hv3 = v3.CastToVector(); + + if (Length() == hv2.Length()) + { + double * p1 = data; + double * p2 = hv2.data; + double * p3 = hv3.data; + + for (INDEX i = Length(); i > 0; i--) + { + (*p1) += (scal * (*p2) + scal3 * (*p3)); + p1++; p2++; p3++; + } + } + else + (*myerr) << "Vector::Add: illegal dimension" << endl; + return *this; + } + +BaseVector & Vector :: Set (double scal, const BaseVector & v2) + { + const Vector & hv2 = v2.CastToVector(); + + if (Length() == hv2.Length()) + { + double * p1 = data; + double * p2 = hv2.data; + + for (INDEX i = Length(); i > 0; i--) + { + (*p1) = scal * (*p2); + p1++; p2++; + } + } + else + (*myerr) << "Vector::Set: illegal dimension" << endl; + return *this; + } + + +BaseVector & Vector :: Set2 (double scal , const BaseVector & v2, + double scal3, const BaseVector & v3) + { + const Vector & hv2 = v2.CastToVector(); + const Vector & hv3 = v3.CastToVector(); + + + if (Length() == hv2.Length()) + { + double * p1 = data; + double * p2 = hv2.data; + double * p3 = hv3.data; + + for (INDEX i = Length(); i > 0; i--) + { + (*p1) = scal * (*p2) + scal3 * (*p3); + p1++; p2++; p3++; + } + } + else + (*myerr) << "Vector::Set: illegal dimension" << endl; + return *this; + } + + +void Vector :: GetPart (int startpos, BaseVector & v2) const +{ + Vector & hv2 = v2.CastToVector(); + + if (Length() >= startpos + v2.Length() - 1) + { + const double * p1 = &Get(startpos); + double * p2 = &hv2.Elem(1); + + memcpy (p2, p1, hv2.Length() * sizeof(double)); + } + else + MyError ("Vector::GetPart: Vector to short"); +} + + +// NEW RM +void Vector :: SetPart (int startpos, const BaseVector & v2) +{ + const Vector & hv2 = v2.CastToVector(); + INDEX i; + INDEX n = v2.Length(); + + if (Length() >= startpos + n - 1) + { + double * p1 = &Elem(startpos); + const double * p2 = &hv2.Get(1); + + for (i = 1; i <= n; i++) + { + (*p1) = (*p2); + p1++; + p2++; + } + } + else + MyError ("Vector::SetPart: Vector to short"); +} + +void Vector :: AddPart (int startpos, double val, const BaseVector & v2) +{ + const Vector & hv2 = v2.CastToVector(); + INDEX i; + INDEX n = v2.Length(); + + if (Length() >= startpos + n - 1) + { + double * p1 = &Elem(startpos); + const double * p2 = &hv2.Get(1); + + for (i = 1; i <= n; i++) + { + (*p1) += val * (*p2); + p1++; + p2++; + } + } + else + MyError ("Vector::AddPart: Vector to short"); +} + + + + +double Vector :: operator* (const BaseVector & v2) const + { + const Vector & hv2 = v2.CastToVector(); + + double sum = 0; + double * p1 = data; + double * p2 = hv2.data; + + if (Length() == hv2.Length()) + { + for (INDEX i = Length(); i > 0; i--) + { + sum += (*p1) * (*p2); + p1++; p2++; + } + } + else + (*myerr) << "Scalarproduct illegal dimension" << endl; + return sum; + } + +void Vector :: SetRandom () + { + INDEX i; + for (i = 1; i <= Length(); i++) + Elem(i) = rand (); + + double l2 = L2Norm(); + if (l2 > 0) + (*this) /= l2; + // Elem(i) = 1.0 / double(i); + // Elem(i) = drand48(); + } + + +/* +TempVector Vector :: operator- () const + { + Vector & sum = *(Vector*)Copy(); + + if (sum.Length () == Length()) + { + for (INDEX i = 1; i <= Length(); i++) + sum.Set (i, Get(i)); + } + else + (*myerr) << "operator+ (Vector, Vector): sum.Length() not ok" << endl; + return sum; + } +*/ + +BaseVector & Vector::operator= (const Vector & v2) + { + SetLength (v2.Length()); + + if (data == v2.data) return *this; + + if (v2.Length() == Length()) + memcpy (data, v2.data, sizeof (double) * Length()); + else + (*myerr) << "Vector::operator=: not allocated" << endl; + + return *this; + } + +BaseVector & Vector::operator= (const BaseVector & v2) + { + const Vector & hv2 = v2.CastToVector(); + + SetLength (hv2.Length()); + + if (data == hv2.data) return *this; + + if (hv2.Length() == Length()) + memcpy (data, hv2.data, sizeof (double) * Length()); + else + (*myerr) << "Vector::operator=: not allocated" << endl; + + return *this; + } + + +BaseVector & Vector::operator= (double scal) + { + if (!Length()) (*myerr) << "Vector::operator= (double) : data not allocated" + << endl; + + for (INDEX i = 1; i <= Length(); i++) + Set (i, scal); + + return *this; + } + + +BaseVector * Vector :: Copy () const + { + return new Vector (*this); + } + + +void Vector :: Swap (BaseVector & v2) + { + Vector & hv2 = v2.CastToVector(); + swap (length, hv2.length); + swap (data, hv2.data); + } + + + + +void Vector :: GetElementVector (const ARRAY<INDEX> & pnum, + BaseVector & elvec) const +{ + int i; + Vector & helvec = elvec.CastToVector(); + for (i = 1; i <= pnum.Size(); i++) + helvec.Elem(i) = Get(pnum.Get(i)); +} + +void Vector :: SetElementVector (const ARRAY<INDEX> & pnum, + const BaseVector & elvec) +{ + int i; + const Vector & helvec = elvec.CastToVector(); + for (i = 1; i <= pnum.Size(); i++) + Elem(pnum.Get(i)) = helvec.Get(i); +} + + +void Vector :: AddElementVector (const ARRAY<INDEX> & pnum, + const BaseVector & elvec) +{ + int i; + const Vector & helvec = elvec.CastToVector(); + for (i = 1; i <= pnum.Size(); i++) + Elem(pnum.Get(i)) += helvec.Get(i); +} +} +#endif diff --git a/Netgen/libsrc/linalg/vector.hpp b/Netgen/libsrc/linalg/vector.hpp new file mode 100644 index 0000000000..acba491792 --- /dev/null +++ b/Netgen/libsrc/linalg/vector.hpp @@ -0,0 +1,485 @@ +#ifndef FILE_VECTOR +#define FILE_VECTOR + +/* *************************************************************************/ +/* File: vector.hh */ +/* 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.data[i]; + return *this; + } + + FlatVector & Set (double scal, const FlatVector & v2) + { + for (int i = 0; i < s; i++) + data[i] = scal * v2.data[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.data[i] + scal2 * v2.data[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 +{ + +public: + Vector () + { s = 0; data = 0; } + Vector (int as) + { s = as; data = new double[s]; } + ~Vector () + { delete [] data; } + + Vector & operator= (const FlatVector & v) + { memcpy (data, &v.Get(1), 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; + delete [] data; + data = new double [s]; + } + } + +}; + + +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; +} + + + + + + + + + + +#ifdef OLDVEC + +class TempVector; +class Vector; +class BlockVector; + +/** Data types for vectors. + + Every Vector data structure is derived from a BaseVector class. + A BaseVector provides virtual functions for the scalar-vector + and vector-vector operations. + If the return value of a function is a vector, then there should + be used a TempVector class. This avoids one additional constructor/ + destructor call. + Finally, a Vector - class contains the data of a Vector in dense + form. + + Vector - Operations: + + Vector ( x ) Constructor empty, with given length or + given vector to copy + + SetLength () + ChangeLength() Change vector-length with/without destroing the vector + Length() return vector-length + + Copy() Construct a vector of same type and contents + + operator() Save vector access + Set, Get, Elem: Fast vector access for setting, receiving and reference + + +, -, *, =, +=, -=, *=, /= + virtual vector operations + + SupNorm, L2Norm, L1Norm, Min, Max + Vector operations + + Set (s, v), Add (s, v) + Fast scalar-vector operations + + Print () stream output of a vector + +*/ + +class BaseVector +{ +protected: + /// + INDEX length; + /// + static double shit; + +public: + /// + BaseVector (); + /// + BaseVector (INDEX alength); + /// + virtual ~BaseVector () { }; + /// + virtual void SetSize (INDEX asize) { SetLength(asize); } + /// + virtual void SetLength (INDEX alength); + /// + virtual void ChangeLength (INDEX alength); + /// Size should be prefered !!! + INDEX Length () const { return length; } + /// + INDEX Size() const { return length; } + + // NEW RM ---> in BlockVector + // rtual void SetBlockLength (INDEX blength) = 0; + + /// + virtual BaseVector & operator= (const BaseVector & /* v2 */) { return *this; } + /// + virtual BaseVector & operator= (double /* scal */) { return *this; } + + /// + virtual double & operator() (INDEX /* i */) { return shit; } + /// + virtual double operator() (INDEX /* i */) const { return 0; } + + /// + virtual double SupNorm () const = 0; + /// + virtual double L2Norm () const = 0; + /// + virtual double L1Norm () const = 0; + /// + virtual double Min () const = 0; + /// + virtual double Max () const = 0; + + /// + virtual BaseVector & operator+= (const BaseVector & v2) = 0; + /// + virtual BaseVector & operator-= (const BaseVector & v2) = 0; + /// + virtual BaseVector & operator*= (double scal) = 0; + /// + virtual BaseVector & operator/= (double scal); + + /// + virtual TempVector operator+ (const BaseVector & v2) const; + /// + virtual TempVector operator- (const BaseVector & v2) const; + /// + virtual TempVector operator- () const; + /// + virtual double operator* (const BaseVector & v2) const = 0; + /// + friend TempVector operator* (const BaseVector & v1, double scal); + /// + friend TempVector operator/ (const BaseVector & v1, double scal); + /// + friend TempVector operator* (double scal, const BaseVector & v1); + + /// + virtual BaseVector & Add (double /* scal */, const BaseVector & /* v2 */) { return *this; } + /// + virtual BaseVector & Add2 (double /* scal */, const BaseVector & /* v2 */, + double /* scal3 */, const BaseVector & /* v3 */) { return *this; } + /// + virtual BaseVector & Set (double /* scal */, const BaseVector & /* v2 */) { return *this; } + /// + virtual BaseVector & Set2 (double /* scal */, const BaseVector & /* v2 */, + double /* scal3 */, const BaseVector & /* v3 */) { return *this; } + + /// + virtual void SetRandom () { }; + + + /// + virtual void GetPart (int /* startpos */, + BaseVector & /* v2*/ ) const { }; + /// + virtual void SetPart (int /* startpos */, + const BaseVector & /* v2 */) { }; + /// + virtual void AddPart (int /* startpos */, double /* val */, + const BaseVector & /* v2 */) { }; + + /// + virtual void GetElementVector (const ARRAY<INDEX> & pnum, + BaseVector & elvec) const; + /// + virtual void SetElementVector (const ARRAY<INDEX> & pnum, + const BaseVector & elvec); + /// + virtual void AddElementVector (const ARRAY<INDEX> & pnum, + const BaseVector & elvec); + + /// + friend ostream & operator<<(ostream & s, const BaseVector & v); + /// + virtual ostream & Print (ostream & s) const { return s; } + + /// + virtual BaseVector * Copy () const; + /// + virtual int IsVector () const { return 0; } + /// + virtual int IsBlockVector () const { return 0; } + /// + virtual Vector & CastToVector () { return *(Vector*)this; } + /// + virtual const Vector & CastToVector () const { return *(Vector*)this; } + /// + virtual BlockVector & CastToBlockVector () { return *(BlockVector*)this; } + /// + virtual const BlockVector & CastToBlockVector () const { return *(BlockVector*)this; } + }; + + +/// +class TempVector : public BaseVector +{ + /// + BaseVector * vec; + + public: + /// + TempVector (BaseVector & v1) { vec = & v1; } + /// + ~TempVector (); + /// + virtual Vector & CastToVector () + { return vec->CastToVector(); } + /// + virtual const Vector & CastToVector () const + { return vec->CastToVector(); } + /// + virtual BlockVector & CastToBlockVector () + { return vec->CastToBlockVector(); } + /// + virtual const BlockVector & CastToBlockVector () const + { return vec->CastToBlockVector(); } + + + /// + virtual BaseVector & operator+= (const BaseVector & /* v2 */) { return *this; } + /// + virtual BaseVector & operator-= (const BaseVector & /* v2 */) { return *this; } + /// + virtual BaseVector & operator*= (double /* scal */) { return *this; } + /// + virtual double operator* (const BaseVector & /* v2 */) const { return 0; } + + /// + virtual double SupNorm () const { return vec->SupNorm(); } + /// + virtual double L2Norm () const { return vec->L2Norm(); } + /// + virtual double L1Norm () const { return vec->L1Norm(); } + /// + virtual double Min () const { return vec->Min(); } + /// + virtual double Max () const { return vec->Max(); } + + /// + virtual void Swap (BaseVector &) { }; + /// + virtual BaseVector * Copy () const; + + + }; + + +/// +class Vector : public BaseVector +{ + /// + double * data; + /// + static double shit; + +public: + /// + Vector (); + /// + Vector (INDEX alength); + /// + Vector (const Vector & v2); + /// + virtual ~Vector (); + + /// + virtual void SetLength (INDEX alength); + /// + virtual void ChangeLength (INDEX alength); + /// NEW RM + virtual void SetBlockLength (INDEX blength); + + /// + virtual BaseVector & operator= (const BaseVector & v2); + /// + virtual BaseVector & operator= (const Vector & v2); + /// + virtual BaseVector & operator= (double scal); + + /// + double & operator() (INDEX i); + /// + double operator() (INDEX i) const; + + /// + virtual double SupNorm () const; + /// + virtual double L2Norm () const; + /// + virtual double L1Norm () const; + /// + virtual double Min () const; + /// + virtual double Max () const; + + /// + virtual BaseVector & operator+= (const BaseVector & v2); + /// + virtual BaseVector & operator-= (const BaseVector & v2); + /// + virtual BaseVector & operator*= (double scal); + + /// + virtual double operator* (const BaseVector & v2) const; + + + /// + virtual BaseVector & Add (double scal, const BaseVector & v2); + /// + virtual BaseVector & Add2 (double scal, const BaseVector & v2, + double scal3, const BaseVector & v3); + /// + virtual BaseVector & Set (double scal, const BaseVector & v2); + /// + virtual BaseVector & Set2 (double scal , const BaseVector & v2, + double scal3, const BaseVector & v3); + + /// + virtual void GetPart (int startpos, BaseVector & v2) const; + /// + virtual void SetPart (int startpos, const BaseVector & v2); + /// + virtual void AddPart (int startpos, double val, const BaseVector & v2); + + /// + virtual void SetRandom (); + + /// + virtual ostream & Print (ostream & s) const; + /// + virtual BaseVector * Copy () const; + /// + virtual void Swap (BaseVector &); + + /// + const double & Get (INDEX i) const { return data[i-1]; } + /// + void Set (INDEX i, double v) { data[i-1] = v; } + /// + double & Elem (INDEX i) { return data[i-1]; } + + /// + virtual int IsVector () const { return 1; } + + + /// + virtual void GetElementVector (const ARRAY<INDEX> & pnum, + BaseVector & elvec) const; + /// + virtual void SetElementVector (const ARRAY<INDEX> & pnum, + const BaseVector & elvec); + /// + virtual void AddElementVector (const ARRAY<INDEX> & pnum, + const BaseVector & elvec); + }; + +#endif + +#endif + + diff --git a/Netgen/libsrc/makefile.inc b/Netgen/libsrc/makefile.inc new file mode 100644 index 0000000000..6a98d84e43 --- /dev/null +++ b/Netgen/libsrc/makefile.inc @@ -0,0 +1,46 @@ +# +# +# Make-Include-File for library +# Joachim Schoeberl, 17.04.96 +# +# +CPP_DIR=../.. +LIBSRC_DIR=$(CPP_DIR)/libsrc +LIB_DIR=$(CPP_DIR)/lib/$(MACHINE) +OCC_DIR=../../occ +# OCC_DIR=/opt/OpenCASCADE5.1/ros +OCCINC_DIR=$(OCC_DIR)/inc +# OCCLIB_DIR=$(OCC_DIR)/lib +# +include $(LIBSRC_DIR)/makefile.mach.$(MACHINE) +# +CPLUSPLUSFLAGS1 = -c -I$(LIBSRC_DIR)/include -I$(OCCINC_DIR) +# +ARFLAGS = r +# +LIBB=$(LIB_DIR)/lib$(lib).a +# +.PRECIOUS: .cpp .hh +.SUFFIXES: .cpp .o +# +.cpp.o: + $(CPLUSPLUS) $(CPLUSPLUSFLAGS1) $(CPLUSPLUSFLAGS2) $(CPLUSPLUSFLAGSLIBRARY) $< +# +# +$(LIBB):: $(LIB_DIR) +# +# make lib from sources: +# +$(LIBB):: $(src) + $(CPLUSPLUS) $(CPLUSPLUSFLAGS1) $(CPLUSPLUSFLAGS2) $(CPLUSPLUSFLAGSLIBRARY) $? + @$(AR) $(ARFLAGS) $@ *.o + -@$(RM) *.o + -@$(RANLIB) $@ +# +# +# +$(LIB_DIR) : + -@mkdir $(CPP_DIR)/lib + @mkdir $(LIB_DIR) +# +# diff --git a/Netgen/libsrc/makefile.mach.INTEL b/Netgen/libsrc/makefile.mach.INTEL new file mode 100644 index 0000000000..c445191a24 --- /dev/null +++ b/Netgen/libsrc/makefile.mach.INTEL @@ -0,0 +1,18 @@ +# +# Machine dependent make include file for Intel compiler +# +CC=icc +CPLUSPLUS=$(CC) +AR=ar +LINK=$(CC) +MAKE=make +RM=rm +RANLIB=ranlib +# +# Machine dependent flags: +# +CFLAGS2 = +CPLUSPLUSFLAGS2 = -O2 -wd654 -DLINUX -DOPENGL +# +LINKFLAGS2 = -L/usr/openwin/lib -L/usr/X11R6/lib -L/usr/lib/GL3.5 + diff --git a/Netgen/libsrc/makefile.mach.LINUX b/Netgen/libsrc/makefile.mach.LINUX new file mode 100644 index 0000000000..44e4a5ccdd --- /dev/null +++ b/Netgen/libsrc/makefile.mach.LINUX @@ -0,0 +1,20 @@ +# +# Machine dependent make include file for gcc +# +# +CC=gcc +CPLUSPLUS=$(CC) +AR=ar +LINK=$(CC) +MAKE=make +RM=rm +RANLIB=ranlib +# +# Machine dependent flags: +# +CFLAGS2 = +CPLUSPLUSFLAGS2 = -O2 -I/usr/X11R6/include -DLINUX -DOPENGL +# +LINKFLAGS2 = -L/usr/openwin/lib -L/usr/X11R6/lib + +SYSLIB2 = -lstdc++ diff --git a/Netgen/libsrc/makefile.mach.SGI b/Netgen/libsrc/makefile.mach.SGI new file mode 100644 index 0000000000..b75920ce26 --- /dev/null +++ b/Netgen/libsrc/makefile.mach.SGI @@ -0,0 +1,19 @@ +# +# Machine dependent make include file +# +CC=CC +CPLUSPLUS=$(CC) +AR=ar +LINK=$(CC) +MAKE=make -k +RM=rm +RANLIB=echo +# +CFLAGS2 = +# +CPLUSPLUSFLAGS2 = -O2 -LANG:std -OPT:Olimit=0 -I/usr/X11R6/include -I/usr/local/include -I/nfs/home/joachim/tcltk/include -DOPENGL -woff 1174 -woff 1682 -woff 1681 -woff 1552 -DOLDCINCLUDE +# -woff 3262,3203,1174,1110 +# +# -I/usr/freeware/include +LINKFLAGS2 = -LANG:std -L/usr/openwin/lib -L/usr/freeware/lib32 -L/usr/X11R6/lib -L/usr/local/lib -w -L/nfs/home/joachim/tcltk/lib + diff --git a/Netgen/libsrc/makefile.mach.SGIGCC b/Netgen/libsrc/makefile.mach.SGIGCC new file mode 100644 index 0000000000..c43363c5e7 --- /dev/null +++ b/Netgen/libsrc/makefile.mach.SGIGCC @@ -0,0 +1,53 @@ +# +# Machine dependent make include file +# +# +# CC=/opt/experimental/bin/gcc +CC=/usr/freeware/bin/gcc +CPLUSPLUS=$(CC) +AR=ar +LINK=$(CC) +MAKE=make +RM=rm +RANLIB=ranlib +# +# Machine dependent flags: +# +CFLAGS2 = +# I/opt/experimental/include/g++-v3 +CPLUSPLUSFLAGS2 = -O2 -save-temps -fverbose-asm -I/usr/local/include -I/usr/freeware/include -I/usr/freeware/include/tcl -I/usr/freeware/include/tk -I/usr/include/GL3.5 -DLINUX -DOPENGL -I../lapack/\ + -ftemplate-depth-99 +# -finline-limit=10000 +# -mcpu=pentiumpro -fforce-addr -Wdisabled-optimization -funroll-loops +# -funroll-all-loops +# -dr -dt -df +# -fforce-addr \ +# -fssa -fdce -fschedule-insns2 -fstrict-aliasing -frename-registers \ +# -freg-struct-return +# -fargument-noalias-global -fargument-noalias \ +# --param max-gcse-memory=100000000 \ +# --param max-delay-slot-live-search=100000 \ +# --param max-pending-list-length=10000 \ +# -fssa \ +# -fomit-frame-pointer -fno-enforce-eh-specs -fno-defer-pop \ +# -fforce-mem -fstrict-aliasing \ +# -fno-implement-inlines \ +# -foptimize-sibling-calls \ +# -frerun-cse-after-loop -fcse-follow-jumps -fexpensive-optimizations \ +# -fstrength-reduce -frerun-loop-opt -fcse-skip-blocks -fgcse \ +# -pedantic \ +# -fno-implicit-templates +# +# -I/usr/local/intel/mkl/INCLUDE +# -fsyntax-only +# -fomit-frame-pointer +# -funroll-loops +# +LINKFLAGS2 = -L/usr/local/lib -L/usr/openwin/lib -L/usr/X11R6/lib -L/usr/lib/GL3.5 -L/usr/freeware/lib32 -L/usr/X11R6/lib -L/usr/local/lib + +# SYSLIB2 = libstdc++. +# SYSLIB2 = -lstdc++ +# -lgcc_s +# SYSLIB2 = -L/usr/lib/lapack -lblas -lstdc++ + + diff --git a/Netgen/libsrc/makefile.mach.SUN b/Netgen/libsrc/makefile.mach.SUN new file mode 100644 index 0000000000..f927ae06f1 --- /dev/null +++ b/Netgen/libsrc/makefile.mach.SUN @@ -0,0 +1,16 @@ +# +# Machine dependent make include file +# +CC=CC +CPLUSPLUS=$(CC) +AR=ar +LINK=$(CC) +MAKE=make -k +RM=rm +RANLIB=ranlib +# +CFLAGS2 = +# +CPLUSPLUSFLAGS2 = -fast -O2 -I/usr/openwin/share/include +LINKFLAGS2 = -L/usr/openwin/lib + diff --git a/Netgen/libsrc/meshing/Makefile b/Netgen/libsrc/meshing/Makefile new file mode 100644 index 0000000000..c0f17db986 --- /dev/null +++ b/Netgen/libsrc/meshing/Makefile @@ -0,0 +1,16 @@ +src = adfront2.cpp adfront3.cpp geomsearch.cpp global.cpp \ + meshtool.cpp \ + netrule2.cpp netrule3.cpp parser2.cpp parser3.cpp ruler2.cpp ruler3.cpp \ + meshtype.cpp meshclass.cpp improve2.cpp smoothing2.cpp improve3.cpp smoothing3.cpp \ + improve2gen.cpp meshing2.cpp meshing3.cpp \ + localh.cpp delaunay.cpp topology.cpp clusters.cpp \ + tetrarls.cpp triarls.cpp quadrls.cpp meshfunc.cpp meshfunc2d.cpp \ + refine.cpp bisect.cpp zrefine.cpp secondorder.cpp hprefinement.cpp \ + boundarylayer.cpp specials.cpp msghandler.cpp \ + pyramidrls.cpp pyramid2rls.cpp prism2rls.cpp curvedelems.cpp curvedelems2.cpp +# +lib = mesh +libpath = libsrc/meshing +# +include ../makefile.inc +# diff --git a/Netgen/libsrc/meshing/adfront2.cpp b/Netgen/libsrc/meshing/adfront2.cpp new file mode 100644 index 0000000000..e273144501 --- /dev/null +++ b/Netgen/libsrc/meshing/adfront2.cpp @@ -0,0 +1,535 @@ +/* + Advancing front class for surfaces +*/ + +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + + /* +AdFront2::FrontPoint2 :: FrontPoint2 () +{ + globalindex = 0; + nlinetopoint = 0; + frontnr = INT_MAX-10; // attention: overflow on calculating INT_MAX + 1 + mgi = NULL; +} + */ + +AdFront2::FrontPoint2 :: FrontPoint2 (const Point3d & ap, PointIndex agi, + MultiPointGeomInfo * amgi) +{ + p = ap; + globalindex = agi; + nlinetopoint = 0; + frontnr = INT_MAX-10; + + 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::FrontPoint2 :: ~FrontPoint2 () +{ +// if (mgi) delete mgi; +} +*/ + + +AdFront2::FrontLine :: FrontLine () +{ + lineclass = 1; +} + +AdFront2::FrontLine :: FrontLine (const INDEX_2 & al) +{ + l = al; + lineclass = 1; +} + + + + + + +AdFront2 :: AdFront2 (const Box3d & aboundingbox) + : boundingbox(aboundingbox), + linesearchtree(boundingbox.PMin(), boundingbox.PMax()), + cpointsearchtree(boundingbox.PMin(), boundingbox.PMax()) +{ + nfl = 0; + // allflines = new INDEX_2_HASHTABLE<int> (100000); + allflines = 0; + + minval = 0; + starti = 1; +} + +AdFront2 :: ~AdFront2 () +{ + delete allflines; +} + + +void AdFront2 :: PrintOpenSegments (ostream & ost) const +{ + if (nfl > 0) + { + int i; + ost << nfl << " open front segments left:" << endl; + for (i = 1; i <= lines.Size(); i++) + if (lines.Get(i).Valid()) + ost << GetGlobalIndex (lines.Get(i).L().I1()) << "-" + << GetGlobalIndex (lines.Get(i).L().I2()) << endl; + + } +} + + +void AdFront2 :: GetPoints (ARRAY<Point3d> & apoints) const +{ + for (int i = 0; i < points.Size(); i++) + apoints.Append (points[i].P()); +} + + + + + +INDEX AdFront2 :: AddPoint (const Point3d & p, PointIndex globind, + MultiPointGeomInfo * mgi) +{ + // inserts at empty position or resizes array + int pi; + + if (delpointl.Size() != 0) + { + pi = delpointl.Last(); + delpointl.DeleteLast (); + + points.Elem(pi) = FrontPoint2 (p, globind, mgi); + } + else + { + pi = points.Append (FrontPoint2 (p, globind, mgi)); + } + + if (mgi) + { + cpointsearchtree.Insert (p, pi); + } + + return pi; +} + + +INDEX AdFront2 :: AddLine (INDEX pi1, INDEX pi2, + const PointGeomInfo & gi1, const PointGeomInfo & gi2) +{ + int minfn; + INDEX li; + + FrontPoint2 & p1 = points.Elem(pi1); + FrontPoint2 & p2 = points.Elem(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.Elem(li) = FrontLine (INDEX_2(pi1, pi2)); + } + else + { + li = lines.Append(FrontLine (INDEX_2(pi1, pi2))); + } + + + if (!gi1.trignum || !gi2.trignum) + { + cout << "ERROR: in AdFront::AddLine, illegal geominfo" << endl; + } + + lines.Elem(li).SetGeomInfo (gi1, gi2); + + Box3d lbox; + lbox.SetPoint(p1.P()); + lbox.AddPoint(p2.P()); + + linesearchtree.Insert (lbox.PMin(), lbox.PMax(), li); + + /* + (*testout) << "add front line: " << p1.P() << " - " << p2.P() + << " Dist = " << Dist (p1.P(), p2.P()) << endl; + */ + + 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 (INDEX li) +{ + int i; + INDEX pi; + + nfl--; + + for (i = 1; i <= 2; i++) + { + pi = lines.Get(li).L().I(i); + points.Elem(pi).RemoveLine(); + + if (!points.Get(pi).Valid()) + { + delpointl.Append (pi); + if (points.Elem(pi).mgi) + { + cpointsearchtree.DeleteElement (pi); + delete points.Elem(pi).mgi; + points.Elem(pi).mgi = NULL; + } + } + } + + if (allflines) + { + allflines->Set (INDEX_2 (GetGlobalIndex (lines.Get(li).L().I1()), + GetGlobalIndex (lines.Get(li).L().I2())), 2); + } + + lines.Elem(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 (INDEX li) +{ + lines.Elem(li).IncrementClass(); +} + + +void AdFront2 :: ResetClass (INDEX li) +{ + lines.Elem(li).ResetClass(); +} + + + +int AdFront2 :: SelectBaseLine (Point3d & p1, Point3d & p2, + const PointGeomInfo *& geominfo1, + const PointGeomInfo *& geominfo2) +{ + int i, hi; + + /* + int minval; + int baselineindex; + minval = INT_MAX; + for (i = 1; i <= lines.Size(); i++) + if (lines.Get(i).Valid()) + { + hi = lines.Get(i).LineClass() + + points.Get(lines.Get(i).L().I1()).FrontNr() + + points.Get(lines.Get(i).L().I2()).FrontNr(); + + if (hi < minval) + { + minval = hi; + baselineindex = i; + } + } + */ + + /* + static int minval = 0; + static int starti = 1; + */ + int baselineindex = 0; + + for (i = starti; i <= lines.Size(); i++) + { + if (lines.Get(i).Valid()) + // const ILINE * lp = &lines.Get(i).l; + // if (lp->I1() >= 0) + { + hi = lines.Get(i).LineClass() + + points.Get(lines.Get(i).L().I1()).FrontNr() + + points.Get(lines.Get(i).L().I2()).FrontNr(); + + if (hi <= minval) + { + minval = hi; + baselineindex = i; + break; + } + } + } + + if (!baselineindex) + { + (*testout) << "nfl = " << nfl << " tot l = " << lines.Size() << endl; + minval = INT_MAX; + for (i = 1; i <= lines.Size(); i++) + if (lines.Get(i).Valid()) + { + hi = lines.Get(i).LineClass() + + points.Get(lines.Get(i).L().I1()).FrontNr() + + points.Get(lines.Get(i).L().I2()).FrontNr(); + + if (hi < minval) + { + minval = hi; + baselineindex = i; + } + } + } + starti = baselineindex+1; + + + + p1 = points.Get(lines.Get(baselineindex).L().I1()).P(); + p2 = points.Get(lines.Get(baselineindex).L().I2()).P(); + geominfo1 = &lines.Get(baselineindex).GetGeomInfo(1); + geominfo2 = &lines.Get(baselineindex).GetGeomInfo(2); + 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) +{ + int i, j, ii; + int pstind; + int pi; + Point3d midp, p0; + + pstind = lines.Get(baselineindex).L().I1(); + p0 = points.Get(pstind).P(); + + loclines.Append(lines.Get(baselineindex).L()); + lindex.Append(baselineindex); + + static ARRAY<int> nearlines; + + nearlines.SetSize(0); + double dist = xh; + linesearchtree.GetIntersecting (p0 - Vec3d(dist, dist, dist), + p0 + Vec3d(dist, dist, dist), + nearlines); + + // for (i = 1; i <= lines.Size(); i++) + for (ii = 1; ii <= nearlines.Size(); ii++) + { + i = nearlines.Get(ii); + + if (lines.Get(i).Valid() && i != baselineindex) + { + const Point3d & p1 = points.Get(lines.Get(i).L().I1()).P(); + const Point3d & p2 = points.Get(lines.Get(i).L().I2()).P(); + + midp = Center (p1, p2); + + if (Dist (midp, p0) <= xh + 0.5 * Dist (p1, p2)) + { + loclines.Append(lines.Get(i).L()); + lindex.Append(i); + } + } + } + + static ARRAY<int> invpindex; + + invpindex.SetSize (points.Size()); + for (i = 1; i <= loclines.Size(); i++) + for (j = 1; j <= 2; j++) + invpindex.Elem(loclines.Get(i).I(j)) = 0; + + for (i = 1; i <= loclines.Size(); i++) + { + for (j = 1; j <= 2; j++) + { + pi = loclines.Get(i).I(j); + if (invpindex.Get(pi) == 0) + { + pindex.Append (pi); + invpindex.Elem(pi) = pindex.Size(); + loclines.Elem(i).I(j) = locpoints.Append (points.Get(pi).P()); + } + else + loclines.Elem(i).I(j) = invpindex.Get(pi); + } + } + + pgeominfo.SetSize (locpoints.Size()); + for (i = 1; i <= pgeominfo.Size(); i++) + pgeominfo.Elem(i).Init(); + + + for (i = 1; i <= loclines.Size(); i++) + for (j = 1; j <= 2; j++) + { + int lpi = loclines.Get(i).I(j); + + const PointGeomInfo & gi = + lines.Get(lindex.Get(i)).GetGeomInfo (j); + 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 (i = 1; i <= locpoints.Size(); i++) + { + int pi = pindex.Get(i); + + + + if (points.Get(pi).mgi) + for (j = 1; j <= points.Get(pi).mgi->GetNPGI(); j++) + pgeominfo.Elem(i).AddPointGeomInfo (points.Get(pi).mgi->GetPGI(j)); +/* + { + for (j = 0; j < points.Get(pi).mgi->cnt; j++) + { + pgeominfo.Elem(i).mgi[pgeominfo.Elem(i).cnt] = + points.Get(pi).mgi->mgi[j]; + pgeominfo.Elem(i).cnt++; + } + } +*/ + } + + + + /* + for (i = 1; i <= points.Size(); i++) + if (points.Get(i).Valid() && + Dist (points.Get(i).P(), p0) <= xh && + invpindex.Get(i) == 0) + { + invpindex.Elem(i) = + locpoints.Append (points.Get(pi).P()); + } + */ + + + 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.Get(baselineindex).LineClass(); +} + + + +void AdFront2 :: SetStartFront () +{ + INDEX i; + int j; + + for (i = 1; i <= lines.Size(); i++) + if (lines.Get(i).Valid()) + for (j = 1; j <= 2; j++) + points.Elem(lines.Get(i).L().I(j)).DecFrontNr(0); +} + + + + +void AdFront2 :: Print (ostream & ost) const +{ + INDEX i; + + ost << points.Size() << " Points: " << endl; + for (i = 1; i <= points.Size(); i++) + if (points.Get(i).Valid()) + ost << i << " " << points.Get(i).P() << endl; + + ost << nfl << " Lines: " << endl; + for (i = 1; i <= lines.Size(); i++) + if (lines.Get(i).Valid()) + ost << lines.Get(i).L().I1() << " - " << lines.Get(i).L().I2() << endl; + + ost << flush; +} +} diff --git a/Netgen/libsrc/meshing/adfront2.hpp b/Netgen/libsrc/meshing/adfront2.hpp new file mode 100644 index 0000000000..b7a45e34e8 --- /dev/null +++ b/Netgen/libsrc/meshing/adfront2.hpp @@ -0,0 +1,336 @@ +#ifndef FILE_ADFRONT2 +#define FILE_ADFRONT2 + +/**************************************************************************/ +/* File: adfront2.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Okt. 95 */ +/**************************************************************************/ + +/* + Advancing front class for surfaces +*/ + + +/* +#define FRONTLINE_GEOMINFO_SIZE 8 +#define FRONTPOINT_GEOMINFO_SIZE 4 +*/ + +/// +class AdFront2 +{ + + /// + class FrontPoint2 + { + /// coordinates + Point3d p; + /// global node index + PointIndex globalindex; + /// number of front lines connected to point + int nlinetopoint; + /// distance to original boundary + int frontnr; + // char geominfo[FRONTLINE_GEOMINFO_SIZE]; + public: + /// + MultiPointGeomInfo * mgi; + + /// + FrontPoint2 () + { + globalindex = -1; + nlinetopoint = 0; + frontnr = INT_MAX-10; // attention: overflow on calculating INT_MAX + 1 + mgi = NULL; + } + + /// + FrontPoint2 (const Point3d & ap, PointIndex agi, + MultiPointGeomInfo * amgi); + /// + ~FrontPoint2 () { ; } + + /// + const Point3d & P () 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; } + + /// + 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 + // char geominfo[FRONTLINE_GEOMINFO_SIZE]; + PointGeomInfo geominfo[2]; + public: + + FrontLine (); + /// + FrontLine (const INDEX_2 & al); + + /// + 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; + }; + + + + /// + ARRAY<FrontPoint2> points; /// front points + ARRAY<FrontLine> lines; /// front lines + + Box3d boundingbox; + Box3dTree linesearchtree; /// search tree for lines + Point3dTree cpointsearchtree; /// search tree for cone points + + ARRAY<INDEX> delpointl; /// list of deleted front points + ARRAY<INDEX> dellinel; /// list of deleted front lines + + INDEX nfl; /// number of front lines; + INDEX_2_HASHTABLE<int> * allflines; /// all front lines ever have been + + + int minval; + int starti; + +public: + /// + // AdFront2 (); + AdFront2 (const Box3d & aboundingbox); + /// + ~AdFront2 (); + + /// + void GetPoints (ARRAY<Point3d> & apoints) const; + /// + void Print (ostream & ost) const; + + /// + bool Empty () const + { + return nfl == 0; + } + /// + int GetNFL () const { return nfl; } + /// + int SelectBaseLine (Point3d & p1, Point3d & p2, + const PointGeomInfo *& geominfo1, + const PointGeomInfo *& geominfo2); + + /// + int GetLocals (int baseline, + ARRAY<Point3d> & locpoints, + ARRAY<MultiPointGeomInfo> & pgeominfo, + ARRAY<INDEX_2> & loclines, // local index + ARRAY<INDEX> & pindex, + ARRAY<INDEX> & lindex, + double xh); + + /// + void DeleteLine (INDEX li); + /// + INDEX AddPoint (const Point3d & p, PointIndex globind, + MultiPointGeomInfo * mgi = NULL); + /// + INDEX AddLine (INDEX pi1, INDEX pi2, + const PointGeomInfo & gi1, const PointGeomInfo & gi2); + /// + int ExistsLine (int gpi1, int gpi2); + /// + void IncrementClass (INDEX li); + /// + void ResetClass (INDEX li); + + /// + const PointGeomInfo & GetLineGeomInfo (int li, int lend) const + { return lines.Get(li).GetGeomInfo (lend); } + /// + + PointIndex GetGlobalIndex (int pi) const + { + return points.Get(pi).GlobalIndex(); + } + /// + void SetStartFront (); + /// + void PrintOpenSegments (ostream & ost) const; +}; + + + + + + +/* +inline int AdFront2::FrontPoint2 :: Valid () const +{ + return nlinetopoint >= 0; +} +*/ +/* +inline const Point3d & AdFront2::FrontPoint2 :: P () const +{ + return p; +} + +inline PointIndex AdFront2::FrontPoint2 :: GlobalIndex () const +{ + return globalindex; +} + +inline void AdFront2::FrontPoint2 :: AddLine () +{ + nlinetopoint++; +} + +inline void AdFront2::FrontPoint2 :: RemoveLine () +{ + nlinetopoint--; + if (nlinetopoint == 0) + nlinetopoint = -1; +} + +inline int AdFront2::FrontPoint2 :: FrontNr () const +{ + return frontnr; +} + +inline void AdFront2::FrontPoint2 :: DecFrontNr (int afrontnr) +{ + if (frontnr > afrontnr) frontnr = afrontnr; +} +*/ + + + + + + + + +/* +inline int AdFront2::FrontLine :: Valid () const +{ + return l.I1() != 0; +} + +inline void AdFront2::FrontLine :: Invalidate () +{ + l.I1() = 0; + l.I2() = 0; + lineclass = 1000; +} + +inline const INDEX_2 & AdFront2::FrontLine :: L () const +{ + return l; +} + +inline int AdFront2::FrontLine :: LineClass () const +{ + return lineclass; +} + + +inline void AdFront2::FrontLine :: IncrementClass () +{ + lineclass++; +} + +inline void AdFront2::FrontLine :: ResetClass () +{ + lineclass = 1; +} + + +inline int AdFront2 :: Empty () const +{ + return nfl == 0; +} + +inline INDEX AdFront2 :: GetGlobalIndex (INDEX pi) const +{ + return points.Get(pi).GlobalIndex(); +} +*/ +#endif + + + diff --git a/Netgen/libsrc/meshing/adfront3.cpp b/Netgen/libsrc/meshing/adfront3.cpp new file mode 100644 index 0000000000..657d0bc12b --- /dev/null +++ b/Netgen/libsrc/meshing/adfront3.cpp @@ -0,0 +1,895 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +/* ********************** FrontPoint ********************** */ + +namespace netgen +{ + +FrontPoint3 :: FrontPoint3 () +{ + globalindex = 0; + nfacetopoint = 0; + frontnr = 1000; + cluster = 0; +} + + +FrontPoint3 :: FrontPoint3 (const Point3d & 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 Element2d & af) +{ + f = af; + oldfront = 0; + qualclass = 1; + hashvalue = 0; +} + +void FrontFace :: Invalidate () +{ + f.Delete(); // PNum(1) = 0; + 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 () +{ + if (facetree) + delete facetree; + if (connectedpairs) + delete connectedpairs; +} + +void AdFront3 :: GetPoints (ARRAY<Point3d> & apoints) const +{ + for (PointIndex pi = PointIndex::BASE; + pi < points.Size()+PointIndex::BASE; pi++) + + apoints.Append (points[pi].P()); +} + + +INDEX AdFront3 :: AddPoint (const Point3d & 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 Element2d & 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) +{ + int i; + INDEX pi; + + nff--; + + for (i = 1; i <= faces.Get(fi).Face().GetNP(); i++) + { + pi = faces.Get(fi).Face().PNum(i); + points.Elem(pi).RemoveFace(); + if (!points.Elem(pi).Valid()) + delpointl.Append (pi); + } + + const Element2d & face = faces.Get(fi).Face(); + const Point3d & p1 = points.Get(face.PNum(1)).P(); + const Point3d & p2 = points.Get(face.PNum(2)).P(); + const Point3d & p3 = points.Get(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.Get(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> (GetNP()); + + // (*testout) << "addconnectedpair " << apair << endl; + connectedpairs->Add1 (apair.I1(), apair.I2()); + connectedpairs->Add1 (apair.I2(), apair.I1()); + + return 0; +} + + + +void AdFront3 :: IncrementClass (INDEX fi) +{ + faces.Elem(fi).IncrementQualClass(); +} + + +void AdFront3 :: ResetClass (INDEX fi) +{ + faces.Elem(fi).ResetQualClass(); +} + + + +void AdFront3 :: CreateTrees () +{ + int i, j; + PointIndex pi; + Point3d pmin, pmax; + + for (pi = PointIndex::BASE; + pi < GetNP()+PointIndex::BASE; pi++) + { + const Point3d & 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); + if (facetree) + delete facetree; + + facetree = new Box3dTree (pmin, pmax); + + for (i = 1; i <= GetNF(); i++) + { + const Element2d & el = GetFace(i); + pmin = GetPoint (el[0]); + pmax = pmin; + for (j = 1; j < 3; j++) + { + const Point3d & 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 Point3d & pmin, const Point3d & 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 () +{ + int i, j, hi; + + hi = 0; + for (i = 1; i <= faces.Size(); i++) + if (faces.Get(i).Valid()) + { + hi++; + faces.Elem(hi) = faces.Get(i); + } + + faces.SetSize (nff); + + int np = points.Size(); + + + for (i = 1; i <= np; i++) + points.Elem(i).cluster = i; + + int change; + do + { + change = 0; + for (i = 1; i <= faces.Size(); i++) + { + const Element2d & el = faces.Get(i).Face(); + + int mini = points.Get(el.PNum(1)).cluster; + int maxi = mini; + + for (j = 2; j <= 3; j++) + { + int ci = points.Get(el.PNum(j)).cluster; + if (ci < mini) mini = ci; + if (ci > maxi) maxi = ci; + } + + if (mini < maxi) + { + change = 1; + for (j = 1; j <= 3; j++) + points.Elem(el.PNum(j)).cluster = mini; + } + } + } + while (change); + + BitArray usecl(np); + usecl.Clear(); + for (i = 1; i <= faces.Size(); i++) + { + usecl.Set (points.Get(faces.Get(i).Face().PNum(1)).cluster); + faces.Elem(i).cluster = + points.Get(faces.Get(i).Face().PNum(1)).cluster; + } + int cntcl = 0; + for (i = 1; i <= np; i++) + if (usecl.Test(i)) + cntcl++; + + ARRAY<double> clvol (np); + for (i = 1; i <= np; i++) + clvol.Elem(i) = 0; + + for (i = 1; i <= faces.Size(); i++) + { + const Element2d & face = faces.Get(i).Face(); + + const Point3d & p1 = points.Get(face.PNum(1)).P(); + const Point3d & p2 = points.Get(face.PNum(2)).P(); + const Point3d & p3 = points.Get(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.Get(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.Elem (faces.Get(i).cluster) += vi; + } + + + int negvol = 0; + for (i = 1; i <= clvol.Size(); i++) + { + if (clvol.Elem(i) < 0) + { + negvol = 1; + } + } + + if (negvol) + { + for (i = 1; i <= faces.Size(); i++) + faces.Elem(i).cluster = 1; + for (i = 1; i <= points.Size(); i++) + points.Elem(i).cluster = 1; + } + + if (hashon) + hashtable.Create(); +} + + + +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.Get(faces.Get(i).Face().PNum(1)).FrontNr() + + points.Get(faces.Get(i).Face().PNum(2)).FrontNr() + + points.Get(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.Get(faces.Get(i).Face().PNum(1)).FrontNr() + + points.Get(faces.Get(i).Face().PNum(2)).FrontNr() + + points.Get(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<Element2d> & locfaces, // local index + ARRAY<PointIndex> & pindex, + ARRAY<INDEX> & findex, + INDEX_2_HASHTABLE<int> & getconnectedpairs, + float xh, + float relh, + INDEX& facesplit) +{ + if (hashon && faces.Size() < 500) { hashon=0; } + if (hashon && !hashcreated) + { + hashtable.Create(); hashcreated=1; + } + + INDEX i, j; + INDEX pstind; + INDEX pi; + Point3d midp, p0; + static ARRAY<int> invpindex; + + static ARRAY<Element2d> locfaces2; //all local faces in radius xh + static ARRAY<int> locfaces3; // all faces in outer radius relh + static 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.Get(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 Element2d & face = faces.Get(i).Face(); + if (faces.Get(i).cluster == cluster && faces.Get(i).Valid() && i != fstind) + { + const Point3d & p1 = points.Get(face.PNum(1)).P(); + const Point3d & p2 = points.Get(face.PNum(2)).P(); + const Point3d & p3 = points.Get(face.PNum(3)).P(); + + Box3d b2; + b2.SetPoint (p1); + b2.AddPoint (p2); + b2.AddPoint (p3); + + /* + midp = Center (p1, p2, p3); + + if (Dist2 (midp, p0) <= xh*xh) + { + locfaces2.Append(faces.Get(i).Face()); + findex2.Append(i); + } + */ + 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 Element2d & face = locfaces2.Get(i); + const Point3d & p1 = points.Get(face.PNum(1)).P(); + const Point3d & p2 = points.Get(face.PNum(2)).P(); + const Point3d & p3 = points.Get(face.PNum(3)).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.Elem(pi) = 0; + } + + /* + for (i = 1; i <= points.Size(); i++) + invpindex.Elem(i) = 0; + */ + for (i = 1; i <= locfaces.Size(); i++) + { + for (j = 1; j <= locfaces.Get(i).GetNP(); j++) + { + pi = locfaces.Get(i).PNum(j); + if (invpindex.Get(pi) == 0) + { + pindex.Append (pi); + invpindex.Elem(pi) = pindex.Size(); + locfaces.Elem(i).PNum(j) = locpoints.Append (points.Get(pi).P()); + } + else + locfaces.Elem(i).PNum(j) = invpindex.Get(pi); + + } + } + + + + if (connectedpairs) + { + for (i = 1; i <= locpoints.Size(); i++) + { + int pi = pindex.Get(i); + if (pi >= 1 && pi <= connectedpairs->Size ()) + { + for (j = 1; j <= connectedpairs->EntrySize(pi); j++) + { + int oi = connectedpairs->Get(pi, 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 (coned, 1); + } + } + } + } + } + + + + + /* + 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<Element2d> & groupelements, + ARRAY<PointIndex> & pindex, + ARRAY<INDEX> & findex + ) const +{ + static ARRAY<char> pingroup; + INDEX i; + int j, changed, fused; + + pingroup.SetSize(points.Size()); + + for (i = 1; i <= pingroup.Size(); i++) + pingroup.Elem(i) = 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 Element2d & face = faces.Get(i).Face(); + + + 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()) + { + 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 Element2d & face = faces.Get(i).Face(); + for (j = 1; j <= 3; j++) + points.Elem(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; + } + */ +} + + +int AdFront3 :: Inside (const Point3d & p) const +{ + int i, 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 (i = 1; i <= faces.Size(); i++) + if (faces.Get(i).Valid()) + { + const Point3d & p1 = points[faces.Get(i).Face().PNum(1)].P(); + const Point3d & p2 = points[faces.Get(i).Face().PNum(2)].P(); + const Point3d & p3 = points[faces.Get(i).Face().PNum(3)].P(); + + v1 = p2 - p1; + v2 = p3 - p1; + + a.Elem(1, 1) = v1.X(); + a.Elem(2, 1) = v1.Y(); + a.Elem(3, 1) = v1.Z(); + a.Elem(1, 2) = v2.X(); + a.Elem(2, 2) = v2.Y(); + a.Elem(3, 2) = v2.Z(); + a.Elem(1, 3) = -n.X(); + a.Elem(2, 3) = -n.Y(); + a.Elem(3, 3) = -n.Z(); + + b.Elem(1) = p.X() - p1.X(); + b.Elem(2) = p.Y() - p1.Y(); + b.Elem(3) = p.Z() - p1.Z(); + + CalcInverse (a, ainv); + ainv.Mult (b, u); + + if (u.Elem(1) >= 0 && u.Elem(2) >= 0 && u.Elem(1)+u.Elem(2) <= 1 && + u.Elem(3) > 0) + { + cnt++; + } + } + + return (cnt % 2); +} + + + + + +int AdFront3 :: SameSide (const Point3d & lp1, const Point3d & lp2, + const ARRAY<int> * testfaces) const +{ + int i, ii, cnt; + + const Point3d *line[2]; + line[0] = &lp1; + line[1] = &lp2; + + + cnt = 0; + + Point3d pmin(lp1); + Point3d pmax(lp1); + pmin.SetToMin (lp2); + pmax.SetToMax (lp2); + + static ARRAY<int> aprif; + aprif.SetSize(0); + + if (!testfaces) + facetree->GetIntersecting (pmin, pmax, aprif); + else + { + for (i = 1; i <= testfaces->Size(); i++) + aprif.Append (testfaces->Get(i)); + } + + // (*testout) << "test ss, p1,p2 = " << lp1 << lp2 << ", inters = " << aprif.Size() << endl; + // for (i = 1; i <= faces.Size(); i++) + for (ii = 1; ii <= aprif.Size(); ii++) + { + i = aprif.Get(ii); + + if (faces.Get(i).Valid()) + { + const Point3d *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/Netgen/libsrc/meshing/adfront3.hpp b/Netgen/libsrc/meshing/adfront3.hpp new file mode 100644 index 0000000000..50e30c56cb --- /dev/null +++ b/Netgen/libsrc/meshing/adfront3.hpp @@ -0,0 +1,274 @@ +#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 + Point3d 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 Point3d & ap, PointIndex agi); + + /// + const Point3d & 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; +}; + +/// Face in advancing front +class FrontFace +{ + /// + Element2d f; + /// + int qualclass; + /// + char oldfront; + /// + int hashvalue; + /// + int cluster; + +public: + /// + FrontFace (); + /// + FrontFace (const Element2d & af); + /// + const Element2d & Face () const + { return f; } + + /// + int QualClass () const + { return qualclass; } + + /// + void IncrementQualClass () + { qualclass++; } + + /// + void ResetQualClass () + { + if (qualclass > 1) + { + qualclass = 1; + oldfront = 0; + } + } + + /// + int Valid () const + { + return !f.IsDeleted(); // PNum(1) != 0; + } + + /// + 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> * 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; + + /// + class Box3dTree * facetree; +public: + + /// + AdFront3 (); + /// + ~AdFront3 (); + /// + void GetPoints (ARRAY<Point3d> & apoints) const; + /// + int GetNP() const + { return points.Size(); } + /// + const Point3d & GetPoint (PointIndex pi) const + { return points[pi].P(); } + /// + int GetNF() const + { return nff; } + /// + const Element2d & GetFace (int i) const + { return faces.Get(i).Face(); } + /// + void Print () const; + /// + int Empty () const + { return nff == 0; } + /// + int Empty (int elnp) const + { + if (elnp == 4) + return (nff4 == 0); + return (nff - nff4 == 0); + } + /// + int SelectBaseElement (); + + /// + void CreateTrees (); + + /// + void GetIntersectingFaces (const Point3d & pmin, const Point3d & pmax, + ARRAY<int> & ifaces) const; + + /// + void GetFaceBoundingBox (int i, Box3d & box) const; + + /// + int GetLocals (int baseelement, + ARRAY<Point3d> & locpoints, + ARRAY<Element2d> & 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<Element2d> & groupelements, + ARRAY<PointIndex> & pindex, + ARRAY<INDEX> & findex + ) const; + + /// + void DeleteFace (INDEX fi); + /// + INDEX AddPoint (const Point3d & p, PointIndex globind); + /// + INDEX AddFace (const Element2d & e); + /// + INDEX AddConnectedPair (const INDEX_2 & pair); + /// + void IncrementClass (INDEX fi); + /// + void ResetClass (INDEX fi); + /// + void SetStartFront (int baseelnp = 0); + + /// is Point p inside Surface ? + int Inside (const Point3d & p) const; + /// both points on same side ? + int SameSide (const Point3d & lp1, const Point3d & 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/Netgen/libsrc/meshing/bisect.cpp b/Netgen/libsrc/meshing/bisect.cpp new file mode 100644 index 0000000000..39420983c8 --- /dev/null +++ b/Netgen/libsrc/meshing/bisect.cpp @@ -0,0 +1,2298 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ +#include "../interface/writeuser.hpp" + + class MarkedTet; + class MarkedPrism; + class MarkedTri; + class MarkedQuad; + + typedef MoveableArray<MarkedTet> T_MTETS; + typedef MoveableArray<MarkedPrism> T_MPRISMS; + 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 + unsigned char faceedges[4]; + + bool incorder; + unsigned int order:6; + + friend ostream & operator<< (ostream & ost, const MarkedTet & mt); +}; + +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; +}; + +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; +}; + +class MarkedQuad +{ +public: + /// point numbers + PointIndex pnums[4]; + /// + PointGeomInfo pgeominfo[4]; + /// marked for refinement + int marked; + /// surface id + int surfid; + + bool incorder; + unsigned int order:6; +}; + + + + + +ostream & operator<< (ostream & ost, const MarkedTet & mt) +{ + int k; + ost << "MT: " << mt.pnums[0] << " - " << mt.pnums[1] << " - " + << mt.pnums[2] << " - " << mt.pnums[3] << endl + << "marked edge: " << mt.tetedge1 << " - " << mt.tetedge2 + << ", order = " << mt.order << endl; + for (k = 0; k < 4; k++) + ost << mt.faceedges[k] << " "; + ost << endl; + return ost; +} + + + + +void BTSortEdges (const Mesh & mesh, + INDEX_2_CLOSED_HASHTABLE<int> & edgenumber) +{ + cout << "sorting ... " << flush; + + // if (mesh.PureTetMesh()) + if (1) + { + // new, fast version + + ARRAY<INDEX_2> edges; + ARRAY<int> eclasses; + + int i, j, k; + int cntedges = 0; + int goon; + int ned; + + // 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]; + + 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; + } + } + + 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); + } + } + } + + // 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]; + + 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 + { + goon = 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]; + switch (el.GetType()) + { + case PRISM: + case PRISM12: + { + pairs = prismpairs; + break; + } + case PYRAMID: + { + pairs = pyramidpairs; + break; + } + } + + 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); + goon = 1; + } + if (eclasses.Get(eclass2) > + eclasses.Get(eclass1)) + { + eclasses.Elem(eclass2) = + eclasses.Get(eclass1); + goon = 1; + } + } + } + } + while (goon); + + /* + 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); + + QickSort (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); + } + } + } + + else + + { + // old version + + int i, j, k; + 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; + } + } + + 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 goon = 0; + do + { + goon = 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; + } + } + + 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); + goon = 1; + } + if (used2 && !used1) + { + cnt++; + edgenumber.Set (e1, cnt); + goon = 1; + } + } + } + } + while (goon); + } + } + while (found); + } +} + + + + +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; + mt.faceedges[k] = 6 - k - i - j; + } + } + } +} + + + + +void BTDefineMarkedPrism (const Element & el, + INDEX_2_CLOSED_HASHTABLE<int> & edgenumber, + MarkedPrism & mp) +{ + int i, j, k; + + 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; + } + } +} + + + + + + +void BTDefineMarkedTri (const Element2d & el, + INDEX_2_CLOSED_HASHTABLE<int> & edgenumber, + MarkedTri & mt) +{ + int i, j, k; + 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 BTDefineMarkedQuad (const Element2d & el, + INDEX_2_CLOSED_HASHTABLE<int> & edgenumber, + MarkedQuad & mq) +{ + int i, j, k; + for (i = 0; i < 4; i++) + mq.pnums[i] = el[i]; + Swap (mq.pnums[2], mq.pnums[3]); + + mq.marked = 0; + mq.surfid = el.GetIndex(); +} + + + + +// mark elements due to local h +int BTMarkTets (T_MTETS & mtets, + T_MPRISMS & mprisms, + const Mesh & mesh) +{ + int i, j, k; + int step; + + int marked = 0; + + int np = mesh.GetNP(); + Vector hv(np); + for (i = 1; i <= np; i++) + hv.Elem(i) = mesh.GetH (mesh.Point(i)); + + double hfac = 1; + + for (step = 1; step <= 2; step++) + { + for (i = 1; i <= mtets.Size(); i++) + { + double h = 0; + + for (j = 0; j < 3; j++) + for (k = j+1; k < 4; k++) + { + const Point3d & p1 = mesh.Point (mtets.Get(i).pnums[j]); + const Point3d & 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 (j = 0; j < 4; j++) + { + double hi = hv.Get (mtets.Get(i).pnums[j]); + 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 (i = 1; i <= mprisms.Size(); i++) + { + double h = 0; + + for (j = 0; j < 2; j++) + for (k = j+1; k < 3; k++) + { + const Point3d & p1 = mesh.Point (mprisms.Get(i).pnums[j]); + const Point3d & 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 (j = 0; j < 6; j++) + { + double hi = hv.Get (mprisms.Get(i).pnums[j]); + 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) +{ + 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; + + + 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) + newtet2.faceedges[oldtet.tetedge2] = + 6 - oldtet.tetedge1 - j - k; + else + newtet2.faceedges[oldtet.tetedge2] = oldtet.tetedge1; + } + + 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) + newtet1.faceedges[oldtet.tetedge1] = + 6 - oldtet.tetedge2 - j - k; + else + newtet1.faceedges[oldtet.tetedge1] = oldtet.tetedge2; + } + } + + newtet1.matindex = oldtet.matindex; + newtet2.matindex = oldtet.matindex; + newtet1.incorder = 0; + newtet1.order = oldtet.order; + newtet2.incorder = 0; + newtet2.order = oldtet.order; +} + + + + +void BTBisectPrism (const MarkedPrism & oldprism, int newp1, int newp2, + MarkedPrism & newprism1, MarkedPrism & newprism2) +{ + int i, j, k; + + 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 BTBisectTri (const MarkedTri & oldtri, int newp, const PointGeomInfo & newpgi, + MarkedTri & newtri1, MarkedTri & newtri2) +{ + int i, j, k; + + 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, j, k; + + 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]; + } + + 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; + + newquad1.surfid = oldquad.surfid; + newquad2.surfid = oldquad.surfid; + + + int nm = oldquad.marked - 1; + if (nm < 0) nm = 0; + + newquad1.marked = nm; + newquad2.marked = nm; +} + + + + +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; + hanging = 1; + } + + } + 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_MTRIS mtris; +T_MQUADS mquads; + + + +void BisectTetsCopyMesh (Mesh & mesh, const class CSGeometry *, + BisectionOptions & opt) +{ + mtets.SetName ("bisection, tets"); + mprisms.SetName ("bisection, prisms"); + mtris.SetName ("bisection, trigs"); + mquads.SetName ("bisection, quads"); + + 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); + 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, 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; + } + } + } + + 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); + } + } + + + + 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; + + + cout << "copied " << mtets.Size() << " tets, " << mtris.Size() << " trigs" << endl; +} + + +void Refinement :: Bisect (Mesh & mesh, + BisectionOptions & opt) +{ + cout << "Mesh bisection" << endl; + + if (mesh.mglevels == 1) + BisectTetsCopyMesh(mesh, NULL, opt); + + 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; + */ + + + // 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())); + + + for (l = 1; l <= 1; l++) + { + int marked = 0; + if (opt.refinementfilename) + { + ifstream inf(opt.refinementfilename); + cout << "load refinementinfo from file " << opt.refinementfilename << endl; + char ch; + for (i = 1; i <= mtets.Size(); i++) + { + inf >> ch; + mtets.Elem(i).marked = (ch == '1'); + } + marked = 1; + } + + 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; + */ + + cout << "marked elements: " << cntm << endl; + + 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 = + 2*mesh.SurfaceElement(i).TestRefinementFlag(); + // mtris.Elem(cnttrig).marked = 0; + if (mtris.Elem(cnttrig).marked) + cntm++; + } + else + { + cntquad++; + mquads.Elem(cntquad).marked = + mesh.SurfaceElement(i).TestRefinementFlag(); + // mquads.Elem(cntquad).marked = 0; + if (mquads.Elem(cntquad).marked) + cntm++; + } + } + + cout << "with surface-elements: " << cntm << endl; + + 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; + + + + if (opt.refine_hp) + { + cout << "refine hp" << endl; + 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.p1); + singv.Set (seg.p2); + } + 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 (int j = 0; j < 2; j++) + { + int pi = (j == 0) ? seg.p1 : seg.p2; + 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; + + 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); + INDEX_2 edge(oldtet.pnums[oldtet.tetedge1], + oldtet.pnums[oldtet.tetedge2]); + edge.Sort(); + if (cutedges.Used (edge)) + { + newp = cutedges.Get(edge); + } + else + { + Point3d np = Center (mesh.Point (edge.I1()), + mesh.Point (edge.I2())); + newp = mesh.AddPoint (np); + cutedges.Set (edge, newp); + } + + BTBisectTet (oldtet, newp, newtet1, newtet2); + mtets.Elem(i) = newtet1; + mtets.Append (newtet2); + } + + 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 + { + Point3d np = Center (mesh.Point (edge1.I1()), + mesh.Point (edge1.I2())); + newp1 = mesh.AddPoint (np); + cutedges.Set (edge1, newp1); + } + if (cutedges.Used (edge2)) + newp2 = cutedges.Get(edge2); + else + { + Point3d np = Center (mesh.Point (edge2.I1()), + mesh.Point (edge2.I2())); + newp2 = mesh.AddPoint (np); + cutedges.Set (edge2, newp2); + } + + + BTBisectPrism (oldprism, newp1, newp2, newprism1, newprism2); + mprisms.Elem(i) = newprism1; + mprisms.Append (newprism2); + } + + + hangingvol = + MarkHangingTets (mtets, cutedges) + + MarkHangingPrisms (mprisms, cutedges); + + + int nsel = mtris.Size(); + + for (i = 1; i <= nsel; i++) + if (mtris.Elem(i).marked) + { + MarkedTri oldtri; + MarkedTri newtri1, newtri2; + int 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 + { + Point3d np = Center (mesh.Point (edge.I1()), + mesh.Point (edge.I2())); + newp = mesh.AddPoint (np); + cutedges.Set (edge, newp); + } + // newp = cutedges.Get(edge); + + int si = mesh.GetFaceDescriptor (oldtri.surfid).SurfNr(); + // geom->GetSurface(si)->Project (mesh.Point(newp)); + PointGeomInfo npgi; + + if (mesh.PointType(newp) != EDGEPOINT) + PointBetween (mesh.Point (oldpi1), mesh.Point (oldpi2), + 0.5, si, + oldtri.pgeominfo[(oldtri.markededge+1)%3], + oldtri.pgeominfo[(oldtri.markededge+2)%3], + mesh.Point (newp), npgi); + + BTBisectTri (oldtri, newp, npgi, newtri1, newtri2); + + + mtris.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]); + edge1.Sort(); + edge2.Sort(); + + if (cutedges.Used (edge1)) + { + newp1 = cutedges.Get(edge1); + } + else + { + Point3d np = Center (mesh.Point (edge1.I1()), + mesh.Point (edge1.I2())); + newp1 = mesh.AddPoint (np); + cutedges.Set (edge1, newp1); + } + + if (cutedges.Used (edge2)) + { + newp2 = cutedges.Get(edge2); + } + else + { + Point3d np = Center (mesh.Point (edge2.I1()), + mesh.Point (edge2.I2())); + newp2 = mesh.AddPoint (np); + 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) << "project point " << newp1 << " old: " << mesh.Point(newp1); + PointBetween (mesh.Point (edge1.I1()), mesh.Point (edge1.I2()), + 0.5, si, + oldquad.pgeominfo[0], + oldquad.pgeominfo[1], + mesh.Point (newp1), npgi1); + (*testout) << " new: " << mesh.Point(newp1) << endl; + + + PointBetween (mesh.Point (edge2.I1()), mesh.Point (edge2.I2()), + 0.5, si, + oldquad.pgeominfo[2], + oldquad.pgeominfo[3], + mesh.Point (newp2), npgi2); + + + 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.p1, seg.p2); + edge.Sort(); + if (cutedges.Used (edge)) + { + hangingedge = 1; + Segment nseg1 = seg; + Segment nseg2 = seg; + + int newpi = cutedges.Get(edge); + + nseg1.p2 = newpi; + nseg2.p1 = newpi; + + EdgePointGeomInfo newepgi; + + // (*testout) << "move edgepoint " << newpi << " from " << mesh.Point(newpi); + PointBetween (mesh.Point (seg.p1), mesh.Point (seg.p2), + 0.5, seg.surfnr1, seg.surfnr2, + seg.epgeominfo[0], seg.epgeominfo[1], + mesh.Point (newpi), newepgi); + // (*testout) << " to " << mesh.Point (newpi) << endl; + nseg1.epgeominfo[1] = newepgi; + nseg2.epgeominfo[0] = newepgi; + + mesh.LineSegment (i) = nseg1; + mesh.AddSegment (nseg2); + } + } + + } + while (hangingvol || hangingsurf || hangingedge); + + + cout << mtets.Size() << " tets" << endl; + cout << mtris.Size() << " trigs" << endl; + if (mprisms.Size()) + { + cout << mprisms.Size() << " prisms" << endl; + cout << mquads.Size() << " quads" << endl; + } + cout << mesh.GetNP() << " points" << endl; + } + + /* + cout << "mem in mtets: " << endl; + mtets.PrintMemInfo(cout); + cout << "cutedges" << endl; + cutedges.PrintMemInfo(cout); + */ + + // (*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 (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 (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 (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 (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()); + 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) + 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; + } + */ + for (i = 1; i <= cutedges.Size(); i++) + if (cutedges.UsedPos(i)) + { + INDEX_2 edge; + int newpi; + cutedges.GetData (i, edge, 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.UpdateTopology(); + + // 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); + } + } + + } + PrintMessage (5, "Bisection done"); +} + + + + +BisectionOptions :: BisectionOptions () +{ + outfilename = NULL; + mlfilename = NULL; + refinementfilename = NULL; + femcode = NULL; + maxlevel = 50; + usemarkedelements = 0; + refine_hp = 0; +} + + + +void Refinement :: PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi, + const PointGeomInfo & gi1, + const PointGeomInfo & gi2, + Point3d & newp, PointGeomInfo & newgi) +{ + newp = p1+secpoint*(p2-p1); +} + +void Refinement :: PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi1, int surfi2, + const EdgePointGeomInfo & ap1, + const EdgePointGeomInfo & ap2, + Point3d & newp, EdgePointGeomInfo & newgi) +{ + newp = p1+secpoint*(p2-p1); +} + +void Refinement :: ProjectToSurface (Point<3> & p, int surfi) +{ + cout << "Refinement :: ProjectToSurface ERROR: no geometry set" << endl; +}; + + +} diff --git a/Netgen/libsrc/meshing/bisect.hpp b/Netgen/libsrc/meshing/bisect.hpp new file mode 100644 index 0000000000..2d8988de0e --- /dev/null +++ b/Netgen/libsrc/meshing/bisect.hpp @@ -0,0 +1,71 @@ +#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; + 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 CSGeometry *, + ZRefinementOptions & opt); + + + + + +class Refinement +{ +public: + Refinement (); + virtual ~Refinement (); + + void Refine (Mesh & mesh, int levels); + void Bisect (Mesh & mesh, class BisectionOptions & opt); + void MakeSecondOrder (Mesh & mesh); + + virtual void PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi, + const PointGeomInfo & gi1, + const PointGeomInfo & gi2, + Point3d & newp, PointGeomInfo & newgi); + + virtual void PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi1, int surfi2, + const EdgePointGeomInfo & ap1, + const EdgePointGeomInfo & ap2, + Point3d & newp, EdgePointGeomInfo & newgi); + + virtual void ProjectToSurface (Point<3> & p, int surfi); + + + void ValidateSecondOrder (Mesh & mesh); + void ValidateRefinedMesh (Mesh & mesh, + ARRAY<INDEX_2> & parents); + +}; + +#endif diff --git a/Netgen/libsrc/meshing/boundarylayer.cpp b/Netgen/libsrc/meshing/boundarylayer.cpp new file mode 100644 index 0000000000..6f564586b6 --- /dev/null +++ b/Netgen/libsrc/meshing/boundarylayer.cpp @@ -0,0 +1,91 @@ +#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).p1); + bndnodes.Set (mesh.LineSegment(i).p2); + } + } + for (i = 1; i <= mesh.GetNSeg(); i++) + { + int snr = mesh.LineSegment(i).edgenr; + if (snr != surfid) + { + bndnodes.Clear (mesh.LineSegment(i).p1); + bndnodes.Clear (mesh.LineSegment(i).p2); + } + } + + 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).p1; + int p2 = mesh.LineSegment(i).p2; + int p3 = mapto.Get (p1); + if (!p3) p3 = p1; + int p4 = mapto.Get (p2); + if (!p4) p4 = p2; + + Element2d el(4); + 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; +} + +} diff --git a/Netgen/libsrc/meshing/boundarylayer.hpp b/Netgen/libsrc/meshing/boundarylayer.hpp new file mode 100644 index 0000000000..e5a047b6bb --- /dev/null +++ b/Netgen/libsrc/meshing/boundarylayer.hpp @@ -0,0 +1,9 @@ +#ifndef FILE_BOUNDARYLAYER +#define FILE_BOUNDARYLAYER + + +/// +extern void InsertVirtualBoundaryLayer (Mesh & mesh); + + +#endif diff --git a/Netgen/libsrc/meshing/clusters.cpp b/Netgen/libsrc/meshing/clusters.cpp new file mode 100644 index 0000000000..ed76676746 --- /dev/null +++ b/Netgen/libsrc/meshing/clusters.cpp @@ -0,0 +1,253 @@ +#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(); + if (!top.HasEdges()) + return; + + 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) = i; + + 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 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 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/Netgen/libsrc/meshing/clusters.hpp b/Netgen/libsrc/meshing/clusters.hpp new file mode 100644 index 0000000000..b0eea1b5e0 --- /dev/null +++ b/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/Netgen/libsrc/meshing/curvedelems.cpp b/Netgen/libsrc/meshing/curvedelems.cpp new file mode 100644 index 0000000000..fc0e590366 --- /dev/null +++ b/Netgen/libsrc/meshing/curvedelems.cpp @@ -0,0 +1,1910 @@ +#include <mystdlib.h> + +#include "meshing.hpp" + +namespace netgen +{ + + + // computes Gaussean integration formula on (0,1) with n points + // in: Numerical algs in C (or, was it the Fortran book ?) + 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); + } + } + + + +// ---------------------------------------------------------------------------- +// PolynomialBasis +// ---------------------------------------------------------------------------- + + + void PolynomialBasis :: CalcLegendrePolynomials (double x) + { + double p1 = 1.0, p2 = 0.0, p3; + + lp[0] = 1.0; + + for (int j=1; j<=order; j++) + { + p3=p2; p2=p1; + p1=((2.0*j-1.0)*(2*x-1)*p2-(j-1.0)*p3)/j; + lp[j] = p1; + } + } + + + void PolynomialBasis :: CalcDLegendrePolynomials (double x) + { + double p1 = 0., p2 = 0., p3; + + dlp[0] = 0.; + + for (int j = 1; j <= order-1; j++) + { + p3=p2; p2=p1; + p1=((2.*j-1.)*(2*lp[j-1]+(2*x-1)*p2)-(j-1.)*p3)/j; + dlp[j] = p1; + } + } + + + void PolynomialBasis :: CalcF (double x) + { + CalcLegendrePolynomials (x); + + for (int j = 0; j<=order-2; j++) + f[j] = (lp[j+2]-lp[j])/(2.0*(j+1)+1)/2.0; + } + + + void PolynomialBasis :: CalcDf (double x) + { + CalcLegendrePolynomials (x); + + for (int j = 0; j <= order-2; j++) + df[j] = lp[j+1]; + } + + + void PolynomialBasis :: CalcFDf (double x) + { + CalcLegendrePolynomials (x); + + for (int j = 0; j<=order-2; j++) + { + f[j] = (lp[j+2]-lp[j])/(2.0*(j+1)+1)/2.0; + df[j] = lp[j+1]; + } + } + + + void PolynomialBasis :: CalcDDf (double x) + { + CalcLegendrePolynomials (x); + CalcDLegendrePolynomials (x); + + for (int j = 0; j <= order-2; j++) ddf[j] = dlp[j+1]; + } + + + +// ---------------------------------------------------------------------------- +// BaseFiniteElement1D +// ---------------------------------------------------------------------------- + + + void BaseFiniteElement1D :: CalcVertexShapes () + { + vshape[0] = xi(0); + vshape[1] = 1-xi(0); + + vdshape[0] = 1; + vdshape[1] = -1; + + if (edgeorient == -1) + { + Swap (vshape[0], vshape[1]); + Swap (vdshape[0], vdshape[1]); + } + } + + + void BaseFiniteElement1D :: CalcEdgeShapes () + { + b.SetOrder (edgeorder); + b.CalcFDf( 1-xi(0) ); + + for (int k = 2; k <= edgeorder; k++) + { + eshape[k-2] = b.GetF(k); + edshape[k-2] = -b.GetDf(k); + } + } + + + void BaseFiniteElement1D :: CalcEdgeLaplaceShapes () + { + b.SetOrder (edgeorder); + b.CalcDDf( 1-xi(0) ); + + for (int k = 2; k <= edgeorder; k++) + eddshape[k-2] = b.GetDDf(k); + } + + + + +// ---------------------------------------------------------------------------- +// BaseFiniteElement2D +// ---------------------------------------------------------------------------- + + + void BaseFiniteElement2D :: SetElementNumber (int aelnr) + { + int locmaxedgeorder = -1; + + BaseFiniteElement<2> :: SetElementNumber (aelnr); + Element2d elem = mesh[(SurfaceElementIndex) (elnr-1)]; + top.GetSurfaceElementEdges (elnr, &(edgenr[0]), &(edgeorient[0])); + facenr = top.GetSurfaceElementFace (elnr); + faceorient = top.GetSurfaceElementFaceOrientation (elnr); + + for (int v = 0; v < nvertices; v++) + vertexnr[v] = elem[v]; + + for (int e = 0; e < nedges; e++) + { + edgeorder[e] = curv.GetEdgeOrder (edgenr[e]-1); // 1-based + locmaxedgeorder = max2 (edgeorder[e], locmaxedgeorder); + } + + faceorder = curv.GetFaceOrder (facenr-1); // 1-based + CalcNFaceShapes (); + + if (locmaxedgeorder > maxedgeorder) + { + maxedgeorder = locmaxedgeorder; + eshape.SetSize(nedges * (maxedgeorder-1)); + edshape.SetSize(nedges * (maxedgeorder-1)); + } + + if (faceorder > maxfaceorder) + { + maxfaceorder = faceorder; + fshape.SetSize( nfaceshapes ); // number of face shape functions + fdshape.SetSize( nfaceshapes ); + fddshape.SetSize ( nfaceshapes ); + } + }; + + + + +// ---------------------------------------------------------------------------- +// BaseFiniteElement3D +// ---------------------------------------------------------------------------- + + + void BaseFiniteElement3D :: SetElementNumber (int aelnr) + { + int locmaxedgeorder = -1; + int locmaxfaceorder = -1; + int v, f, e; + + BaseFiniteElement<3> :: SetElementNumber (aelnr); + Element elem = mesh[(ElementIndex) (elnr-1)]; + top.GetElementEdges (elnr, &(edgenr[0]), &(edgeorient[0])); + top.GetElementFaces (elnr, &(facenr[0]), &(faceorient[0])); + + for (v = 0; v < nvertices; v++) + vertexnr[v] = elem[v]; + + for (f = 0; f < nfaces; f++) + { + surfacenr[f] = top.GetFace2SurfaceElement (facenr[f]); + surfaceorient[f] = top.GetSurfaceElementFaceOrientation (surfacenr[f]); + } + + for (e = 0; e < nedges; e++) + { + edgeorder[e] = curv.GetEdgeOrder (edgenr[e]-1); // 1-based + locmaxedgeorder = max2 (edgeorder[e], locmaxedgeorder); + } + + for (f = 0; f < nfaces; f++) + { + faceorder[f] = curv.GetFaceOrder (facenr[f]-1); // 1-based + locmaxfaceorder = max2 (faceorder[f], locmaxfaceorder); + } + + CalcNFaceShapes (); + + if (locmaxedgeorder > maxedgeorder) + { + maxedgeorder = locmaxedgeorder; + eshape.SetSize(nedges * (maxedgeorder-1)); + edshape.SetSize(nedges * (maxedgeorder-1)); + } + + if (locmaxfaceorder > maxfaceorder) + { + maxfaceorder = locmaxfaceorder; + fshape.SetSize( nfaces * (maxfaceorder-1) * (maxfaceorder-1)); // number of face shape functions + fdshape.SetSize( nfaces * (maxfaceorder-1) * (maxfaceorder-1)); + } + }; + + + + +// ---------------------------------------------------------------------------- +// FETrig +// ---------------------------------------------------------------------------- + + + void FETrig :: SetReferencePoint (Point<2> axi) + { + BaseFiniteElement2D :: SetReferencePoint (axi); + lambda(0) = xi(0); + lambda(1) = xi(1); + lambda(2) = 1-xi(0)-xi(1); + + dlambda(0,0) = 1; dlambda(0,1) = 0; + dlambda(1,0) = 0; dlambda(1,1) = 1; + dlambda(2,0) = -1; dlambda(2,1) = -1; + } + + + void FETrig :: SetVertexSingularity (int v, int exponent) + { + int i; + if (1-lambda(v) < EPSILON) return; + + Point<3> lamold = lambda; + + Vec<2> dfac; + + double fac = pow(1-lambda(v),exponent-1); + + for (i = 0; i < 2; i++) + { + dfac(i) = -(exponent-1)*pow(1-lambda(v),exponent-2)*dlambda(v,i); + dlambda(v,i) *= exponent * pow(1-lambda(v),exponent-1); + } + + lambda(v) = 1-pow(1-lambda(v),exponent); + + for (i = 0; i < nvertices; i++) + { + if (i == v) continue; + for (int j = 0; j < 2; j++) + dlambda(i,j) = dlambda(i,j) * fac + lamold(i) * dfac(j); + + lambda(i) *= fac; + } + } + + + + void FETrig :: CalcVertexShapes () + { + for (int v = 0; v < nvertices; v++) + { + vshape[v] = lambda(v); + vdshape[v](0) = dlambda(v,0); + vdshape[v](1) = dlambda(v,1); + } + } + + + void FETrig :: CalcEdgeShapes () + { + int index = 0; + for (int e = 0; e < nedges; e++) + { + int i0 = eledge[e][0]-1; + int i1 = eledge[e][1]-1; + + double arg = lambda(i0) + lambda(i1); // = 1-lambda[i2]; + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 2; k <= edgeorder[e]; k++) + { + eshape[index] = 0; + edshape[index] = Vec<2>(0,0); + index++; + } + continue; + } + + if (edgeorient[e] == -1) Swap (i0, i1); // reverse orientation + + double xi = lambda(i1)/arg; + + b1.SetOrder (edgeorder[e]); + b1.CalcFDf (xi); + + double decay = arg; + double ddecay; + + double l0 = lambda(i0); + double l0x = dlambda(i0,0); + double l0y = dlambda(i0,1); + + double l1 = lambda(i1); + double l1x = dlambda(i1,0); + double l1y = dlambda(i1,1); + + for (int k = 2; k <= edgeorder[e]; k++) + { + ddecay = k*decay; + decay *= arg; + + eshape[index] = b1.GetF (k) * decay; + edshape[index] = Vec<2> + (b1.GetDf(k) * (l1x*arg - l1*(l0x+l1x)) * + decay / (arg * arg) + b1.GetF(k) * ddecay * (l0x+l1x), + b1.GetDf(k) * (l1y*arg - l1*(l0y+l1y)) * + decay / (arg * arg) + b1.GetF(k) * ddecay * (l0y+l1y)); + index++; + } + } + // (*testout) << "eshape = " << eshape << ", edshape = " << edshape << endl; + /* + index = 0; + for (int e = 0; e < nedges; e++) + { + int i0 = eledge[e][0]-1; + int i1 = eledge[e][1]-1; + + if (edgeorient[e] == -1) Swap (i0, i1); // reverse orientation + + double x = lambda(i1)-lambda(i0); + double y = 1-lambda(i0)-lambda(i1); + double fy = (1-y)*(1-y); + + // double p3 = 0, p3x = 0, p3y = 0; + // double p2 = -1, p2x = 0, p2y = 0; + // double p1 = x, p1x = 1, p1y = 0; + + double p3 = 0, p3x = 0, p3y = 0; + double p2 = -0.5, p2x = 0, p2y = 0; + double p1 = 0.5*x, p1x = 0.5, p1y = 0; + + for (int j=2; j<= edgeorder[e]; j++) + { + p3=p2; p3x = p2x; p3y = p2y; + p2=p1; p2x = p1x; p2y = p1y; + double c1 = (2.0*j-3) / j; + double c2 = (j-3.0) / j; + + p1 = c1 * x * p2 - c2 * fy * p3; + p1x = c1 * p2 + c1 * x * p2x - c2 * fy * p3x; + p1y = c1 * x * p2y - (c2 * 2 * (y-1) * p3 + c2 * fy * p3y); + eshape[index] = p1; + // edshape[index] = Vec<2> (p1x, p1y); + edshape[index](0) = -2*p1x; + edshape[index](1) = p1y-p1x; + index++; + } + + } + // (*testout) << "eshape = " << eshape << ", edshape = " << edshape << endl; + */ + } + + + void FETrig :: CalcFaceShapes () + { + int index = 0; + + int i0 = elface[0][0]-1; + int i1 = elface[0][1]-1; + int i2 = elface[0][2]-1; + + // sort lambda_i's by the corresponing vertex numbers + + if (vertexnr[i1] < vertexnr[i0]) Swap (i0, i1); + if (vertexnr[i2] < vertexnr[i0]) Swap (i0, i2); + if (vertexnr[i2] < vertexnr[i1]) Swap (i1, i2); + + double arg = lambda(i1) + lambda(i2); + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 0; k < nfaceshapes; k++) + { + fshape[index] = 0; + fdshape[index] = Vec<2>(0,0); + index++; + } + return; + } + + b1.SetOrder (faceorder); + b2.SetOrder (faceorder); + + b1.CalcFDf (lambda(i0)); + b2.CalcFDf (lambda(i2)/arg); + + double decay = 1; + double ddecay; + + double l0 = lambda(i0); + double l1 = lambda(i1); + double l2 = lambda(i2); + double dl0x = dlambda(i0,0); + double dl0y = dlambda(i0,1); + double dl1x = dlambda(i1,0); + double dl1y = dlambda(i1,1); + double dl2x = dlambda(i2,0); + double dl2y = dlambda(i2,1); + + double dargx = dl1x + dl2x; + double dargy = dl1y + dl2y; + + for (int n1 = 2; n1 < faceorder; n1++) + { + ddecay = (n1-1)*decay; + decay *= arg; + + for (int n0 = 2; n0 < faceorder-n1+2; n0++) + { + fshape[index] = b1.GetF(n0) * b2.GetF(n1) * decay; + fdshape[index] = Vec<2> + (b1.GetDf(n0) * dl0x * b2.GetF(n1) * decay + + b1.GetF(n0) * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargx, + b1.GetDf(n0) * dl0y * b2.GetF(n1) * decay + + b1.GetF(n0) * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargy); + index++; + } + } + } + + + + void FETrig :: CalcFaceLaplaceShapes () + { + int index = 0; + + int i0 = elface[0][0]-1; + int i1 = elface[0][1]-1; + int i2 = elface[0][2]-1; + + if (vertexnr[i1] < vertexnr[i0]) Swap (i0, i1); + if (vertexnr[i2] < vertexnr[i0]) Swap (i0, i2); + if (vertexnr[i2] < vertexnr[i1]) Swap (i1, i2); + + double arg = lambda(i1) + lambda(i2); + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 0; k < nfaceshapes; k++) + fddshape[k] = 0; + return; + } + + b1.SetOrder (faceorder); + b2.SetOrder (faceorder); + + b1.CalcFDf (lambda(i0)); + b1.CalcDDf (lambda(i0)); + b2.CalcFDf (lambda(i2)/arg); + b2.CalcDDf (lambda(i2)/arg); + + double decay = 1; + double ddecay = 0; + double dddecay; + + double l0 = lambda(i0); + double l1 = lambda(i1); + double l2 = lambda(i2); + double dl0x = dlambda(i0,0); + double dl0y = dlambda(i0,1); + double dl1x = dlambda(i1,0); + double dl1y = dlambda(i1,1); + double dl2x = dlambda(i2,0); + double dl2y = dlambda(i2,1); + + double dargx = dl1x + dl2x; + double dargy = dl1y + dl2y; + + for (int n1 = 2; n1 < faceorder; n1++) + { + dddecay = (n1-1)*ddecay; + ddecay = (n1-1)*decay; + decay *= arg; + + for (int n0 = 2; n0 < faceorder-n1+2; n0++) + { + fddshape[index] = + + // b1.GetDf(n0) * dl0x * b2.GetF(n1) * decay .... derived + + b1.GetDDf(n0) * dl0x * dl0x * b2.GetF(n1) * decay + + b1.GetDf(n0) * dl0x * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay + + b1.GetDf(n0) * dl0x * b2.GetF(n1) * ddecay * dargx + + + + // b1.GetF(n0) * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay ... derived + + b1.GetDf(n0) * dl0x * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay + + b1.GetF(n0) * b2.GetDDf(n1) * pow((dl2x * arg - l2 * dargx)/(arg*arg),2) * decay + + b1.GetF(n0) * b2.GetDf(n1) * (-2*dargx/arg) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay + + b1.GetF(n0) * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * ddecay * dargx + + + + // b1.GetF(n0) * b2.GetF(n1) * ddecay * dargx ... derived + + b1.GetDf(n0) * dl0x * b2.GetF(n1) * ddecay * dargx + + b1.GetF(n0) * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * ddecay * dargx + + b1.GetF(n0) * b2.GetF(n1) * dddecay * dargx * dargx + + + + // b1.GetDf(n0) * dl0y * b2.GetF(n1) * decay ... derived + + b1.GetDDf(n0) * dl0y * dl0y * b2.GetF(n1) * decay + + b1.GetDf(n0) * dl0y * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay + + b1.GetDf(n0) * dl0y * b2.GetF(n1) * ddecay * dargy + + + + // b1.GetF(n0) * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay ... derived + + b1.GetDf(n0) * dl0y * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay + + b1.GetF(n0) * b2.GetDDf(n1) * pow((dl2y * arg - l2 * dargy)/(arg*arg),2) * decay + + b1.GetF(n0) * b2.GetDf(n1) * (-2*dargy/arg) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay + + b1.GetF(n0) * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * ddecay * dargy + + + + // b1.GetF(n0) * b2.GetF(n1) * ddecay * dargy ... derived + + b1.GetDf(n0) * dl0y * b2.GetF(n1) * ddecay * dargy + + b1.GetF(n0) * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * ddecay * dargy + + b1.GetF(n0) * b2.GetF(n1) * dddecay * dargy * dargy; + + index++; + } + } + } + + + +// ---------------------------------------------------------------------------- +// FEQuad +// ---------------------------------------------------------------------------- + + + void FEQuad :: CalcVertexShapes () + { + vshape[0] = (1-xi(0)) * (1-xi(1)); + vshape[1] = ( xi(0)) * (1-xi(1)); + vshape[2] = ( xi(0)) * ( xi(1)); + vshape[3] = (1-xi(0)) * ( xi(1)); + + vdshape[0] = Vec<2> ( -(1-xi(1)), -(1-xi(0)) ); + vdshape[1] = Vec<2> ( (1-xi(1)), -( xi(0)) ); + vdshape[2] = Vec<2> ( ( xi(1)), ( xi(0)) ); + vdshape[3] = Vec<2> ( -( xi(1)), (1-xi(0)) ); + } + + + void FEQuad :: CalcEdgeShapes () + { + int index = 0; + + double arg0[4] = { xi(0), 1-xi(0), 1-xi(1), xi(1) }; + double arg1[4] = { 1-xi(1), xi(1), 1-xi(0), xi(0) }; + double darg0[4] = { 1, -1, -1, 1 }; + double darg1[4] = { -1, 1, -1, 1 }; + + for (int e = 0; e < nedges; e++) + { + b1.SetOrder (edgeorder[e]); + b1.CalcFDf (edgeorient[e] == 1 ? arg0[e] : 1-arg0[e]); + + double decay = arg1[e]; + double ddecay; + + for (int k = 2; k <= edgeorder[e]; k++, index++) + { + ddecay = k*decay; + decay *= arg1[e]; +// linear decay + eshape[index] = b1.GetF(k) * arg1[e]; + + if (e < 2) + edshape[index] = Vec<2> + (darg0[e] * edgeorient[e] * b1.GetDf(k) * arg1[e], + b1.GetF(k) * darg1[e]); + else + edshape[index] = Vec<2> + (b1.GetF(k) * darg1[e], + darg0[e] * edgeorient[e] * b1.GetDf(k) * arg1[e]); + +// exponential decay +/* eshape[index] = b1.GetF(k) * decay; + + if (e < 2) + edshape[index] = Vec<2> + (darg0[e] * edgeorient[e] * b1.GetDf(k) * decay, + b1.GetF(k) * ddecay * darg1[e]); + else + edshape[index] = Vec<2> + (b1.GetF(k) * ddecay * darg1[e], + darg0[e] * edgeorient[e] * b1.GetDf(k) * decay); +*/ + } + } + } + + + void FEQuad :: CalcFaceShapes () + { + int index = 0; + + // find index of point with smallest number + + int i0 = 0; + for (int i = 1; i < 4; i++) + if (vertexnr[elface[0][i]-1] < vertexnr[elface[0][i0]-1]) i0 = i; + + double x; + double y; + double dxx; + double dxy; + double dyx; + double dyy; + + switch (i0) + { + case 0: + x = xi(0); y = xi(1); + dxx = 1; dxy = 0; + dyx = 0; dyy = 1; + break; + case 1: + x = xi(1); y = 1-xi(0); + dxx = 0; dxy = 1; + dyx = -1; dyy = 0; + break; + case 2: + x = 1-xi(0); y = 1-xi(1); + dxx = -1; dxy = 0; + dyx = 0; dyy = -1; + break; + case 3: + x = 1-xi(1); y = xi(0); + dxx = 0; dxy =-1; + dyx = 1; dyy = 0; + break; + } + + if (vertexnr[elface[0][(i0+1) % 4]-1] > vertexnr[elface[0][(i0+3) % 4]-1]) + { + Swap (x,y); + Swap (dxx, dyx); + Swap (dxy, dyy); + } + + b1.SetOrder (faceorder); + b2.SetOrder (faceorder); + + b1.CalcFDf (x); + b2.CalcFDf (y); + + for (int n0 = 2; n0 <= faceorder; n0++) + for (int n1 = 2; n1 <= faceorder; n1++) + { + fshape[index] = b1.GetF(n0) * b2.GetF(n1); + fdshape[index] = Vec<2> (b1.GetDf(n0) * dxx * b2.GetF(n1) + b1.GetF(n0) * b2.GetDf(n1) * dyx, + b1.GetDf(n0) * dxy * b2.GetF(n1) + b1.GetF(n0) * b2.GetDf(n1) * dyy); + index++; + } + } + + + void FEQuad :: CalcFaceLaplaceShapes () + { + int index = 0; + + // find index of point with smallest number + + int i0 = 0; + for (int i = 1; i < 4; i++) + if (vertexnr[elface[0][i]-1] < vertexnr[elface[0][i0]-1]) i0 = i; + + double x; + double y; + double dxx; + double dxy; + double dyx; + double dyy; + + switch (i0) + { + case 0: + x = xi(0); y = xi(1); + dxx = 1; dxy = 0; + dyx = 0; dyy = 1; + break; + case 1: + x = xi(1); y = 1-xi(0); + dxx = 0; dxy = 1; + dyx = -1; dyy = 0; + break; + case 2: + x = 1-xi(0); y = 1-xi(1); + dxx = -1; dxy = 0; + dyx = 0; dyy = -1; + break; + case 3: + x = 1-xi(1); y = xi(0); + dxx = 0; dxy =-1; + dyx = 1; dyy = 0; + break; + } + + if (vertexnr[elface[0][(i0+1) % 4]-1] > vertexnr[elface[0][(i0+3) % 4]-1]) + { + Swap (x,y); + Swap (dxx, dyx); + Swap (dxy, dyy); + } + + b1.SetOrder (faceorder); + b2.SetOrder (faceorder); + + b1.CalcFDf (x); + b1.CalcDDf (x); + b2.CalcFDf (y); + b2.CalcDDf (y); + + for (int n0 = 2; n0 <= faceorder; n0++) + for (int n1 = 2; n1 <= faceorder; n1++) + { + fddshape[index] = + b1.GetDDf(n0) * dxx * dxx * b2.GetF(n1) + + 2* b1.GetDf(n0) * dxx * b2.GetDf(n1) * dyx + + b1.GetF(n0) * b2.GetDDf(n1) * dyx * dyx + + + b1.GetDDf(n0) * dxy * dxy * b2.GetF(n1) + + 2* b1.GetDf(n0) * dxy * b2.GetDf(n1) * dyy + + b1.GetF(n0) * b2.GetDDf(n1) * dyy * dyy; + + index++; + } + } + + + +// ---------------------------------------------------------------------------- +// FETet +// ---------------------------------------------------------------------------- + + + void FETet :: SetReferencePoint (Point<3> axi) + { + BaseFiniteElement3D :: SetReferencePoint (axi); + + lambda(0) = xi(0); + lambda(1) = xi(1); + lambda(2) = xi(2); + lambda(3) = 1-xi(0)-xi(1)-xi(2); + + dlambda(0,0) = 1; dlambda(0,1) = 0; dlambda(0,2) = 0; + dlambda(1,0) = 0; dlambda(1,1) = 1; dlambda(1,2) = 0; + dlambda(2,0) = 0; dlambda(2,1) = 0; dlambda(2,2) = 1; + dlambda(3,0) = -1; dlambda(3,1) = -1; dlambda(3,2) = -1; + } + + + void FETet :: CalcVertexShapes () + { + for (int v = 0; v < nvertices; v++) + { + vshape[v] = lambda(v); + vdshape[v](0) = dlambda(v,0); + vdshape[v](1) = dlambda(v,1); + vdshape[v](2) = dlambda(v,2); + } + } + + + void FETet :: CalcEdgeShapes () + { + int index = 0; + + for (int e = 0; e < nedges; e++) + { + int i0 = eledge[e][0]-1; + int i1 = eledge[e][1]-1; + + double arg = lambda(i0)+lambda(i1); + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 2; k <= edgeorder[e]; k++) + { + eshape[index] = 0; + edshape[index] = Vec<3>(0,0,0); + index++; + } + continue; + } + + if (edgeorient[e] == -1) Swap (i0, i1); + + double xi = lambda[i1]/arg; + + b1.SetOrder (edgeorder[e]); + b1.CalcFDf (xi); + + double decay = arg; + double ddecay; + + double l0 = lambda(i0); + double dl0x = dlambda(i0,0); + double dl0y = dlambda(i0,1); + double dl0z = dlambda(i0,2); + + double l1 = lambda(i1); + double dl1x = dlambda(i1,0); + double dl1y = dlambda(i1,1); + double dl1z = dlambda(i1,2); + + double dargx = dl0x + dl1x; + double dargy = dl0y + dl1y; + double dargz = dl0z + dl1z; + + for (int k = 2; k <= edgeorder[e]; k++) + { + ddecay = k*decay; + decay *= arg; + + eshape[index] = b1.GetF (k) * decay; + edshape[index] = Vec<3> + (b1.GetDf(k) * (dl1x*arg - l1*dargx) * + decay / (arg * arg) + b1.GetF(k) * ddecay * dargx, + b1.GetDf(k) * (dl1y*arg - l1*dargy) * + decay / (arg * arg) + b1.GetF(k) * ddecay * dargy, + b1.GetDf(k) * (dl1z*arg - l1*dargz) * + decay / (arg * arg) + b1.GetF(k) * ddecay * dargz); + + index++; + } + } + } + + + void FETet :: CalcFaceShapes () + { + int index = 0; + + for (int f = 0; f < nfaces; f++) + { + int i0 = elface[f][0]-1; + int i1 = elface[f][1]-1; + int i2 = elface[f][2]-1; + + if (vertexnr[i1] < vertexnr[i0]) Swap (i0, i1); + if (vertexnr[i2] < vertexnr[i0]) Swap (i0, i2); + if (vertexnr[i2] < vertexnr[i1]) Swap (i1, i2); + + double arg = lambda(i1) + lambda(i2); + double arg2 = lambda(i0) + lambda(i1) + lambda(i2); + + if (fabs(arg) < EPSILON || fabs(arg2) < EPSILON) // division by 0 + { + for (int k = 0; k < nfaceshapes[f]; k++) + { + fshape[index] = 0; + fdshape[index] = Vec<3>(0,0,0); + index++; + } + continue; + } + + b1.SetOrder (faceorder[f]); + b2.SetOrder (faceorder[f]); + + b1.CalcFDf (lambda(i0)/arg2); + b2.CalcFDf (lambda(i2)/arg); + + double decay = 1; + double ddecay; + + double l0 = lambda(i0); + double l1 = lambda(i1); + double l2 = lambda(i2); + double dl0x = dlambda(i0,0); + double dl0y = dlambda(i0,1); + double dl0z = dlambda(i0,2); + double dl1x = dlambda(i1,0); + double dl1y = dlambda(i1,1); + double dl1z = dlambda(i1,2); + double dl2x = dlambda(i2,0); + double dl2y = dlambda(i2,1); + double dl2z = dlambda(i2,2); + + double dargx = dl1x + dl2x; + double dargy = dl1y + dl2y; + double dargz = dl1z + dl2z; + double darg2x = dl0x + dl1x + dl2x; + double darg2y = dl0y + dl1y + dl2y; + double darg2z = dl0z + dl1z + dl2z; + + for (int n1 = 2; n1 < faceorder[f]; n1++) + { + ddecay = (n1-1)*decay; + decay *= arg; + + double decay2 = arg2; + double ddecay2; + + for (int n0 = 2; n0 < faceorder[f]-n1+2; n0++) + { + ddecay2 = n0*decay2; + decay2 *= arg2; + + fshape[index] = b1.GetF(n0) * b2.GetF(n1) * decay * decay2; + fdshape[index] = Vec<3> + (b1.GetDf(n0) * (dl0x * arg2 - l0 * darg2x)/(arg2*arg2) * b2.GetF(n1) * decay * decay2 + + b1.GetF(n0) * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay * decay2 + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargx * decay2 + + b1.GetF(n0) * b2.GetF(n1) * decay * ddecay2 * darg2x, + + b1.GetDf(n0) * (dl0y * arg2 - l0 * darg2y)/(arg2*arg2) * b2.GetF(n1) * decay * decay2 + + b1.GetF(n0) * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay * decay2 + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargy * decay2 + + b1.GetF(n0) * b2.GetF(n1) * decay * ddecay2 * darg2y, + + b1.GetDf(n0) * (dl0z * arg2 - l0 * darg2z)/(arg2*arg2) * b2.GetF(n1) * decay * decay2 + + b1.GetF(n0) * b2.GetDf(n1) * (dl2z * arg - l2 * dargz)/(arg*arg) * decay * decay2 + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargz * decay2 + + b1.GetF(n0) * b2.GetF(n1) * decay * ddecay2 * darg2z); + + index++; + } + } + } + } + + + + +// ---------------------------------------------------------------------------- +// FEPrism +// ---------------------------------------------------------------------------- + + + void FEPrism :: SetReferencePoint (Point<3> axi) + { + BaseFiniteElement3D :: SetReferencePoint (axi); + + lambda(0) = xi(0); + lambda(1) = xi(1); + lambda(2) = 1-xi(0)-xi(1); + lambda(3) = xi(2); + + dlambda(0,0) = 1; dlambda(0,1) = 0; dlambda(0,2) = 0; + dlambda(1,0) = 0; dlambda(1,1) = 1; dlambda(1,2) = 0; + dlambda(2,0) = -1; dlambda(2,1) = -1; dlambda(2,2) = 0; + dlambda(3,0) = 0; dlambda(3,1) = 0; dlambda(3,2) = 1; + } + + + void FEPrism :: CalcVertexShapes () + { + double zcomp = 1-lambda(3); + + for (int v = 0; v < nvertices; v++) + { + if (v == 3) zcomp = 1-zcomp; + + vshape[v] = lambda(v % 3) * zcomp; + vdshape[v](0) = dlambda(v % 3,0) * zcomp; + vdshape[v](1) = dlambda(v % 3,1) * zcomp; + vdshape[v](2) = lambda(v % 3) * (-dlambda(3,2)); + + if (v >= 3) vdshape[v](2) *= -1; + } + } + + + void FEPrism :: CalcEdgeShapes () + { + int index = 0; + int e; + // triangle edge shapes + + for (e = 0; e < 6; e++) + { + int i0 = (eledge[e][0]-1) % 3; + int i1 = (eledge[e][1]-1) % 3; + + double arg = lambda[i0]+lambda[i1]; + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 2; k <= edgeorder[e]; k++) + { + eshape[index] = 0; + edshape[index] = Vec<3>(0,0,0); + index++; + } + continue; + } + + if (edgeorient[e] == -1) Swap (i0, i1); + + double xi = lambda[i1]/arg; + + b1.SetOrder (edgeorder[e]); + b1.CalcFDf (xi); + + double decay = arg; + double ddecay; + + double zarg = e < 3 ? (1-lambda(3)) : lambda(3); + double zcomp = zarg; + double dzcomp; + + double l0 = lambda(i0); + double dl0x = dlambda(i0,0); + double dl0y = dlambda(i0,1); + + double l1 = lambda(i1); + double dl1x = dlambda(i1,0); + double dl1y = dlambda(i1,1); + + double dargx = dl0x + dl1x; + double dargy = dl0y + dl1y; + + for (int k = 2; k <= edgeorder[e]; k++) + { + ddecay = k*decay; + decay *= arg; + + dzcomp = k*zcomp; + zcomp *= zarg; + + eshape[index] = b1.GetF (k) * decay * zcomp; + edshape[index] = Vec<3> + ((b1.GetDf(k) * (dl1x*arg - l1*dargx) * + decay / (arg * arg) + b1.GetF(k) * ddecay * dargx) * zcomp, + (b1.GetDf(k) * (dl1y*arg - l1*dargy) * + decay / (arg * arg) + b1.GetF(k) * ddecay * dargy) * zcomp, + b1.GetF(k) * decay * dzcomp * (e < 3 ? -1 : 1)); + index++; + } + } + + // rectangle edge shapes + + for (e = 6; e < nedges; e++) + { + int i0 = eledge[e][0]-1; + + double arg = lambda[i0]; + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 2; k <= edgeorder[e]; k++) + { + eshape[index] = 0.; + edshape[index] = Vec<3>(0.,0.,0.); + index++; + } + continue; + } + + double xi = lambda[3]; + + if (edgeorient[e] == -1) xi = 1-xi; + + b1.SetOrder (edgeorder[e]); + b1.CalcFDf (xi); + + double decay = arg; + double ddecay; + + double l0 = lambda(i0); + double l0x = dlambda(i0,0); + double l0y = dlambda(i0,1); + + for (int k = 2; k <= edgeorder[e]; k++) + { + ddecay = k*decay; + decay *= arg; + + eshape[index] = b1.GetF (k) * decay; + edshape[index] = Vec<3> + (b1.GetF(k) * ddecay * l0x, + b1.GetF(k) * ddecay * l0y, + b1.GetDf(k) * edgeorient[e] * decay); + index++; + } + } + } + + + void FEPrism :: CalcFaceShapes () + { + int index = 0; + int f; + + // triangle face parts + + for (f = 0; f < 2; f++) + { + int i0 = elface[f][0]-1; + int i1 = elface[f][1]-1; + int i2 = elface[f][2]-1; + + if (vertexnr[i1] < vertexnr[i0]) Swap (i0, i1); + if (vertexnr[i2] < vertexnr[i0]) Swap (i0, i2); + if (vertexnr[i2] < vertexnr[i1]) Swap (i1, i2); + + i0 = i0 % 3; + i1 = i1 % 3; + i2 = i2 % 3; + + double arg = lambda(i1) + lambda(i2); + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 0; k < nfaceshapes[f]; k++) + { + fshape[index] = 0; + fdshape[index] = Vec<3>(0,0,0); + index++; + } + continue; + } + + b1.SetOrder (faceorder[f]); + b2.SetOrder (faceorder[f]); + + b1.CalcFDf (lambda(i0)); + b2.CalcFDf (lambda(i2)/arg); + + double decay = 1; + double ddecay; + + double l0 = lambda(i0); + double l1 = lambda(i1); + double l2 = lambda(i2); + double dl0x = dlambda(i0,0); + double dl0y = dlambda(i0,1); + double dl0z = dlambda(i0,2); + double dl1x = dlambda(i1,0); + double dl1y = dlambda(i1,1); + double dl1z = dlambda(i1,2); + double dl2x = dlambda(i2,0); + double dl2y = dlambda(i2,1); + double dl2z = dlambda(i2,2); + + double dargx = dl1x + dl2x; + double dargy = dl1y + dl2y; + double dargz = dl1z + dl2z; + + double arg2 = f == 0 ? 1-xi(2) : xi(2); + double darg2z = f == 0 ? -1 : 1; + + for (int n1 = 2; n1 < faceorder[f]; n1++) + { + ddecay = (n1-1)*decay; + decay *= arg; + + double decay2 = arg2; + double ddecay2; + + for (int n0 = 2; n0 < faceorder[f]-n1+2; n0++) + { + ddecay2 = n0*decay2; + decay2 *= arg2; + + fshape[index] = b1.GetF(n0) * b2.GetF(n1) * decay * decay2; + fdshape[index] = Vec<3> + (b1.GetDf(n0) * dl0x * b2.GetF(n1) * decay * decay2 + + b1.GetF(n0) * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay * decay2 + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargx * decay2, + + b1.GetDf(n0) * dl0y * b2.GetF(n1) * decay * decay2 + + b1.GetF(n0) * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay * decay2 + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargy * decay2, + + b1.GetDf(n0) * dl0z * b2.GetF(n1) * decay * decay2 + + b1.GetF(n0) * b2.GetDf(n1) * (dl2z * arg - l2 * dargz)/(arg*arg) * decay * decay2 + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargz * decay2 + + b1.GetF(n0) * b2.GetF(n1) * decay * ddecay2 * darg2z); + + index++; + } + } + } + + + // quad parts + + for (f = 2; f < nfaces; f++) + { + // find index of point with smallest number + + int i, i0 = 0; + for (i = 1; i < 4; i++) + if (vertexnr[elface[f][i]-1] < vertexnr[elface[f][i0]-1]) i0 = i; + + double arg = 0; + double dargx = 0; + double dargy = 0; + double dargz = 0; + for (i = 0; i < 4; i++) + { + arg += lambda((elface[f][i]-1) % 3)/2.0; + dargx += dlambda((elface[f][i]-1) % 3,0)/2.0; + dargy += dlambda((elface[f][i]-1) % 3,1)/2.0; + dargz += dlambda((elface[f][i]-1) % 3,2)/2.0; + } + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 0; k < nfaceshapes[f]; k++) + { + fshape[index] = 0; + fdshape[index] = Vec<3>(0,0,0); + index++; + } + continue; + } + + int i1 = (i0+3) % 4; + int j = (elface[f][i0]-1) % 3; + + double lam = lambda(j)/arg; + double dlamx = (dlambda(j,0)*arg-lambda(j)*dargx)/(arg*arg); + double dlamy = (dlambda(j,1)*arg-lambda(j)*dargy)/(arg*arg); + double dlamz = (dlambda(j,2)*arg-lambda(j)*dargz)/(arg*arg); + + double x; + double z; + double dxx; + double dxy; + double dxz; + double dzx; + double dzy; + double dzz; + + int ratvar; + /* + switch (i0) + { + case 0: + x = xi(2); z = lam; + + dxx = 0; dxy = 0; dxz = 1; + dzx = dlamx; dzy = dlamy; dzz = dlamz; + ratvar = 1; + break; + case 1: + x = 1-lam; z = xi(2); + dxx = -dlamx; dxy = -dlamy; dxz = -dlamz; + dzx = 0; dzy = 0; dzz = 1; + ratvar = 0; + break; + case 2: + x = 1-xi(2); z = 1-lam; + dxx = 0; dxy = 0; dxz = -1; + dzx = -dlamx; dzy = -dlamy; dzz = -dlamz; + ratvar = 1; + break; + case 3: + x = lam; z = 1-xi(2); + dxx = dlamx; dxy = dlamy; dxz = dlamz; + dzx = 0; dzy = 0; dzz = -1; + ratvar = 0; + break; + } + */ + + ratvar = 0; + x = 1-lam; + dxx = -dlamx; dxy = -dlamy; dxz = -dlamz; + if (i0 == 0 || i0 == 1) + { + z = xi(2); + dzx = 0; dzy = 0; dzz = 1; + } + else + { + z = 1-xi(2); + dzx = 0; dzy = 0; dzz = -1; + } + + int ix = i0 ^ 1; + int iz = 3-i0; + + if (vertexnr[elface[f][ix]-1] > vertexnr[elface[f][iz]-1]) + { + Swap (x,z); + Swap (dxx, dzx); + Swap (dxy, dzy); + Swap (dxz, dzz); + ratvar = 1-ratvar; + } + + b1.SetOrder (faceorder[f]); + b2.SetOrder (faceorder[f]); + + b1.CalcFDf (x); + b2.CalcFDf (z); + + double decay = arg; + double ddecay; + + for (int n0 = 2; n0 <= faceorder[f]; n0++) + { + ddecay = n0*decay; + decay *= arg; + + if (ratvar == 1) decay = arg; + + for (int n1 = 2; n1 <= faceorder[f]; n1++) + { + if (ratvar == 1) + { + ddecay = n1*decay; + decay *= arg; + } + + fshape[index] = b1.GetF(n0) * b2.GetF(n1) * decay; + fdshape[index] = Vec<3> + (b1.GetDf(n0) * dxx * b2.GetF(n1) * decay + + b1.GetF(n0) * b2.GetDf(n1) * dzx * decay + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargx, + + b1.GetDf(n0) * dxy * b2.GetF(n1) * decay + + b1.GetF(n0) * b2.GetDf(n1) * dzy * decay + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargy, + + b1.GetDf(n0) * dxz * b2.GetF(n1) * decay + + b1.GetF(n0) * b2.GetDf(n1) * dzz * decay + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargz); + + index++; + } + } + } + } + + + +// ---------------------------------------------------------------------------- +// FEPyramid +// ---------------------------------------------------------------------------- + + + void FEPyramid :: SetReferencePoint (Point<3> axi) + { + BaseFiniteElement3D :: SetReferencePoint (axi); + } + + + void FEPyramid :: CalcVertexShapes () + { + double x = xi(0); + double y = xi(1); + double z = xi(2); + + if (z == 1.) z = 1-1e-10; + vshape[0] = (1-z-x)*(1-z-y) / (1-z); + vshape[1] = x*(1-z-y) / (1-z); + vshape[2] = x*y / (1-z); + vshape[3] = (1-z-x)*y / (1-z); + vshape[4] = z; + + double z1 = 1-z; + double z2 = z1*z1; + + 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 ); + } + + + void FEPyramid :: CalcEdgeShapes () + { + int index = 0; + + for (int e = 0; e < GetNEdges(); e++) + { + for (int k = 2; k <= edgeorder[e]; k++) + { + eshape[index] = 0; + edshape[index] = Vec<3>(0,0,0); + index++; + } + } + } + + + void FEPyramid :: CalcFaceShapes () + { + int index = 0; + + for (int f = 0; f < GetNFaces(); f++) + { + for (int k = 0; k < nfaceshapes[f]; k++) + { + fshape[index] = 0; + fdshape[index] = Vec<3>(0,0,0); + index++; + } + } + } + + + + + +// ---------------------------------------------------------------------------- +// FEHex +// ---------------------------------------------------------------------------- + + + void FEHex :: SetReferencePoint (Point<3> axi) + { + BaseFiniteElement3D :: SetReferencePoint (axi); + } + + + void FEHex :: CalcVertexShapes () + { + double x = xi(0); + double y = xi(1); + double z = xi(2); + + vshape[0] = (1-x)*(1-y)*(1-z); + vshape[1] = x *(1-y)*(1-z); + vshape[2] = x * y *(1-z); + vshape[3] = (1-x)* y *(1-z); + vshape[4] = (1-x)*(1-y)* z; + vshape[5] = x *(1-y)* z; + vshape[6] = x * y * z; + vshape[7] = (1-x)* y * z; + + vdshape[0] = Vec<3>(-(1-y)*(1-z), -(1-x)*(1-z), -(1-x)*(1-y)); + vdshape[1] = Vec<3>( (1-y)*(1-z), -x *(1-z), -x *(1-y)); + vdshape[2] = Vec<3>( y *(1-z), x *(1-z), -x * y); + vdshape[3] = Vec<3>( -y *(1-z), (1-x)*(1-z), -(1-x)*y); + vdshape[4] = Vec<3>(-(1-y)* z, -(1-x)* z, (1-x)*(1-y)); + vdshape[5] = Vec<3>( (1-y)* z, -x * z, x *(1-y)); + vdshape[6] = Vec<3>( y * z, x * z, x * y); + vdshape[7] = Vec<3>( -y * z, (1-x)* z, (1-x)*y); + + } + + + void FEHex :: CalcEdgeShapes () + { + int index = 0; + + for (int e = 0; e < GetNEdges(); e++) + { + for (int k = 2; k <= edgeorder[e]; k++) + { + eshape[index] = 0; + edshape[index] = Vec<3>(0,0,0); + index++; + } + } + } + + + void FEHex :: CalcFaceShapes () + { + int index = 0; + + for (int f = 0; f < GetNFaces(); f++) + { + for (int k = 0; k < nfaceshapes[f]; k++) + { + fshape[index] = 0; + fdshape[index] = Vec<3>(0,0,0); + index++; + } + } + } + + + + + + + + + + int CurvedElements :: IsSurfaceElementCurved (int elnr) const + { + Element2d elem = mesh[(SurfaceElementIndex) elnr]; + + switch (elem.GetType()) + { + case TRIG: + { + FETrig fe2d(*this); + fe2d.SetElementNumber (elnr+1); + return (fe2d.IsCurved()); + break; + } + + case QUAD: + { + FEQuad fe2d(*this); + fe2d.SetElementNumber (elnr+1); + return (fe2d.IsCurved()); + break; + } + + } + return 0; + } + + + + int CurvedElements :: IsElementCurved (int elnr) const + { + Element elem = mesh[(ElementIndex) elnr]; + + switch (elem.GetType()) + { + case TET: + { + FETet fe3d(*this); + fe3d.SetElementNumber (elnr+1); + return (fe3d.IsCurved()); + break; + } + + case PRISM: + { + FEPrism fe3d(*this); + fe3d.SetElementNumber (elnr+1); + return (fe3d.IsCurved()); + break; + } + + case PYRAMID: + { + FEPyramid fe3d(*this); + fe3d.SetElementNumber (elnr+1); + return (fe3d.IsCurved()); + break; + } + + case HEX: + { + FEHex fe3d(*this); + fe3d.SetElementNumber (elnr+1); + return (fe3d.IsCurved()); + break; + } + + } + + return 0; + } + + + void CurvedElements :: CalcSegmentTransformation (double xi, int segnr, + Point<3> * x, Vec<3> * dxdxi) + { + FESegm segm (*this); + segm.SetElementNumber (segnr+1); + segm.SetReferencePoint (Point<1>(xi)); + +// segm.CalcVertexShapes (x != NULL, dxdxi != NULL); + segm.CalcVertexShapes (); + + if (x) + { + (*x) = Point<3>(0,0,0); + for (int v = 0; v < 2; v++) + (*x) = (*x) + segm.GetVertexShape(v) * mesh.Point(segm.GetVertexNr(v)); + } + + if (dxdxi) + { + (*dxdxi) = Vec<3>(0,0,0); + for (int v = 0; v < 2; v++) + (*dxdxi) = (*dxdxi) + segm.GetVertexDShape(v) * mesh.Point(segm.GetVertexNr(v)); + } + + if (segm.GetEdgeOrder() > 1) + { +// segm.CalcEdgeShapes (x != NULL, dxdxi != NULL); + segm.CalcEdgeShapes (); + + if (x) + { + int gindex = edgecoeffsindex[segm.GetEdgeNr()-1]; + for (int k = 2; k <= segm.GetEdgeOrder(); k++, gindex++) + (*x) = (*x) + segm.GetEdgeShape(k-2) * edgecoeffs[gindex]; + } + + if (dxdxi) + { + int gindex = edgecoeffsindex[segm.GetEdgeNr()-1]; + for (int k = 2; k <= segm.GetEdgeOrder(); k++, gindex++) + (*dxdxi) = (*dxdxi) + segm.GetEdgeDShape(k-2) * edgecoeffs[gindex]; + } + } + } + + + + void CurvedElements :: CalcSurfaceTransformation (Point<2> xi, int elnr, + Point<3> * x, Mat<3,2> * dxdxi) + { + Element2d elem = mesh[(SurfaceElementIndex) elnr]; + + BaseFiniteElement2D * fe2d; + + // char locmem[max2(sizeof(FEQuad), sizeof(FETrig))]; + char locmemtrig[sizeof(FETrig)]; + char locmemquad[sizeof(FEQuad)]; + switch (elem.GetType()) + { + case TRIG: fe2d = new (locmemtrig) FETrig (*this); break; + case QUAD: fe2d = new (locmemquad) FEQuad (*this); break; + } + + fe2d->SetElementNumber (elnr+1); + fe2d->SetReferencePoint (xi); + + /* + for (int v = 0; v < fe2d->GetNVertices(); v++) + { + // if (fe2d->GetVertexNr(v) == 1) + fe2d->SetVertexSingularity (v, 2); + } + */ + /* + int imin = 0, imax = 0; + if (fe2d->GetVertexNr(1) < fe2d->GetVertexNr(0)) imin = 1; + if (fe2d->GetVertexNr(2) < fe2d->GetVertexNr(imin)) imin = 2; + if (fe2d->GetVertexNr(1) > fe2d->GetVertexNr(0)) imax = 1; + if (fe2d->GetVertexNr(2) > fe2d->GetVertexNr(imax)) imax = 2; + + fe2d->SetVertexSingularity (imin, 3); + fe2d->SetVertexSingularity (3-imin-imax, 3); + fe2d->SetVertexSingularity (imax, 3); + */ + fe2d->CalcVertexShapes (); + + if (x) + { + (*x) = Point<3>(0,0,0); + for (int v = 0; v < fe2d->GetNVertices(); v++) + (*x) = (*x) + fe2d->GetVertexShape(v) * mesh.Point(fe2d->GetVertexNr(v)); + } + + if (dxdxi) + { + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + (*dxdxi)(i,j) = 0; + + for (int v = 0; v < elem.GetNV(); v++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + (*dxdxi)(i,j) += fe2d->GetVertexDShape(v)(j) * mesh.Point(fe2d->GetVertexNr(v)).X(i+1); + } + + if (IsHighOrder()) + { +// fe2d->CalcEdgeShapes (x != NULL, dxdxi != NULL); + fe2d->CalcEdgeShapes (); + if (x) + { + int index = 0; + for (int e = 0; e < fe2d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe2d->GetEdgeNr(e)-1]; + + for (int k = 2; k <= fe2d->GetEdgeOrder(e); k++, index++, gindex++) + (*x) = (*x) + fe2d->GetEdgeShape(index) * edgecoeffs[gindex]; + } + } + + if (dxdxi) + { + int index = 0; + for (int e = 0; e < fe2d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe2d->GetEdgeNr(e)-1]; + for (int k = 2; k <= fe2d->GetEdgeOrder(e); k++, index++, gindex++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + (*dxdxi)(i,j) += fe2d->GetEdgeDShape(index)(j) * edgecoeffs[gindex](i); + } + } + + if (mesh.GetDimension() == 3) + { +// fe2d->CalcFaceShapes (x != NULL, dxdxi != NULL); + fe2d->CalcFaceShapes (); + + if (x) + { + int gindex = facecoeffsindex[fe2d->GetFaceNr()-1]; + for (int index = 0; index < fe2d->GetNFaceShapes(); index++, gindex++) + { + (*x) = (*x) + fe2d->GetFaceShape(index) * facecoeffs[gindex]; + } + } + + if (dxdxi) + { + int gindex = facecoeffsindex[fe2d->GetFaceNr()-1]; + for (int index = 0; index < fe2d->GetNFaceShapes(); index++, gindex++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + (*dxdxi)(i,j) += fe2d->GetFaceDShape(index)(j) * facecoeffs[gindex](i); + } + } + } + + fe2d -> ~BaseFiniteElement2D(); + } + + + + + void CurvedElements :: CalcElementTransformation (Point<3> xi, int elnr, + Point<3> * x, Mat<3,3> * dxdxi) + { + Element elem = mesh[(ElementIndex) elnr]; + BaseFiniteElement3D * fe3d; + + // char locmem[max2(sizeof(FETet), sizeof(FEPrism))]; + char locmemtet[sizeof(FETet)]; + char locmemprism[sizeof(FEPrism)]; + char locmempyramid[sizeof(FEPyramid)]; + char locmemhex[sizeof(FEHex)]; + switch (elem.GetType()) + { + case TET: fe3d = new (locmemtet) FETet (*this); break; + case PRISM: fe3d = new (locmemprism) FEPrism (*this); break; + case PYRAMID: fe3d = new (locmempyramid) FEPyramid (*this); break; + case HEX: fe3d = new (locmemhex) FEHex (*this); break; + } + + fe3d->SetElementNumber (elnr+1); + fe3d->SetReferencePoint (xi); + + fe3d->CalcVertexShapes (); +// fe3d->CalcVertexShapes (x != NULL, dxdxi != NULL); + + if (x) + { + (*x) = Point<3>(0,0,0); + for (int v = 0; v < fe3d->GetNVertices(); v++) + (*x) += fe3d->GetVertexShape(v) * Vec<3> (mesh.Point(fe3d->GetVertexNr(v))); + } + + if (dxdxi) + { + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)(i,j) = 0; + + for (int v = 0; v < fe3d->GetNVertices(); v++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)(i,j) += fe3d->GetVertexDShape(v)(j) * mesh.Point(fe3d->GetVertexNr(v)).X(i+1); + } + + if (IsHighOrder()) + { +// fe3d->CalcEdgeShapes (x != NULL, dxdxi != NULL); + fe3d->CalcEdgeShapes (); + + if (x) + { + int index = 0; + for (int e = 0; e < fe3d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe3d->GetEdgeNr(e)-1]; + for (int k = 2; k <= fe3d->GetEdgeOrder(e); k++, index++, gindex++) + (*x) += fe3d->GetEdgeShape(index) * edgecoeffs[gindex]; + } + } + + if (dxdxi) + { + int index = 0; + for (int e = 0; e < fe3d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe3d->GetEdgeNr(e)-1]; + for (int k = 2; k <= fe3d->GetEdgeOrder(e); k++, index++, gindex++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)(i,j) += fe3d->GetEdgeDShape(index)(j) * edgecoeffs[gindex](i); + } + } + + if (mesh.GetDimension() == 3) + { + fe3d->CalcFaceShapes (); +// fe3d->CalcFaceShapes (x != NULL, dxdxi != NULL); + + if (x) + { + int index = 0; + for (int f = 0; f < fe3d->GetNFaces(); f++) + { + int gindex = facecoeffsindex[fe3d->GetFaceNr(f)-1]; + for (int k = 0; k < fe3d->GetNFaceShapes(f); k++, index++, gindex++) + (*x) += fe3d->GetFaceShape(index) * facecoeffs[gindex]; + } + } + + if (dxdxi) + { + int index = 0; + for (int f = 0; f < fe3d->GetNFaces(); f++) + { + int gindex = facecoeffsindex[fe3d->GetFaceNr(f)-1]; + for (int k = 0; k < fe3d->GetNFaceShapes(f); k++, index++, gindex++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)(i,j) += fe3d->GetFaceDShape(index)(j) * facecoeffs[gindex](i); + } + } + } + } + + fe3d -> ~BaseFiniteElement3D(); + } + + +} // namespace netgen + + diff --git a/Netgen/libsrc/meshing/curvedelems.hpp b/Netgen/libsrc/meshing/curvedelems.hpp new file mode 100644 index 0000000000..7328d27d66 --- /dev/null +++ b/Netgen/libsrc/meshing/curvedelems.hpp @@ -0,0 +1,835 @@ +#ifndef CURVEDELEMS +#define CURVEDELEMS + +/**************************************************************************/ +/* File: curvedelems.hpp */ +/* Author: Robert Gaisbauer */ +/* Date: 27. Sep. 02 (second version: 30. Jan. 03) */ +/**************************************************************************/ + +#include "bisect.hpp" +#include <iostream> + +#define EPSILON 1e-20 + + + +void ComputeGaussRule (int n, ARRAY<double> & xi, ARRAY<double> & wi); + + + + + +// ---------------------------------------------------------------------------- +// CurvedElements +// ---------------------------------------------------------------------------- + +class CurvedElements +{ + const Mesh & mesh; + const MeshTopology & top; + + bool isHighOrder; + int nvisualsubsecs; + int nIntegrationPoints; + + ARRAY<int> edgeorder; + ARRAY<int> faceorder; + + /* + + ARRAY< Vec<3> > edgecoeffs; + ARRAY< Vec<3> > facecoeffs; + + ARRAY<int> edgecoeffsindex; + ARRAY<int> facecoeffsindex; + + */ + + inline Vec<3> GetEdgeCoeff (int edgenr, int k); + inline Vec<3> GetFaceCoeff (int facenr, int k); + + + void CalcSegmentTransformation (double xi, int segnr, + Point<3> * x = NULL, Vec<3> * dxdxi = NULL); + + void CalcSurfaceTransformation (Point<2> xi, int elnr, + Point<3> * x = NULL, Mat<3,2> * dxdxi = NULL); + + void CalcElementTransformation (Point<3> xi, int elnr, + Point<3> * x = NULL, Mat<3,3> * dxdxi = NULL); + +public: + + Refinement * refinement; + + ARRAY< Vec<3> > edgecoeffs; + ARRAY< Vec<3> > facecoeffs; + + ARRAY<int> edgecoeffsindex; + ARRAY<int> facecoeffsindex; + + + + + + CurvedElements (const Mesh & amesh); + ~CurvedElements(); + + bool IsHighOrder() const + { return isHighOrder; }; + + int GetNVisualSubsecs() const + { return nvisualsubsecs; }; + + const class Mesh & GetMesh() const + { return mesh; }; + + void BuildCurvedElements(Refinement * ref, int polydeg); + + int GetEdgeOrder (int edgenr) const + { return edgeorder[edgenr]; }; + + int GetFaceOrder (int facenr) const + { return faceorder[facenr]; }; + + int IsEdgeCurved (int edgenr) const; + + int IsFaceCurved (int facenr) const; + + int IsSurfaceElementCurved (int elnr) const; + + int IsElementCurved (int elnr) const; + + + void CalcSegmentTransformation (double xi, int segnr, + Point<3> & x) + { CalcSegmentTransformation (xi, segnr, &x, NULL); }; + + void CalcSegmentTransformation (double xi, int segnr, + Vec<3> & dxdxi) + { CalcSegmentTransformation (xi, segnr, NULL, &dxdxi); }; + + void CalcSegmentTransformation (double xi, int segnr, + Point<3> & x, Vec<3> & dxdxi) + { CalcSegmentTransformation (xi, segnr, &x, &dxdxi); }; + + + void CalcSurfaceTransformation (Point<2> & xi, int elnr, + Point<3> & x) + { CalcSurfaceTransformation (xi, elnr, &x, NULL); }; + + void CalcSurfaceTransformation (Point<2> & xi, int elnr, + Mat<3,2> & dxdxi) + { CalcSurfaceTransformation (xi, elnr, NULL, &dxdxi); }; + + void CalcSurfaceTransformation (Point<2> & xi, int elnr, + Point<3> & x, Mat<3,2> & dxdxi) + { CalcSurfaceTransformation (xi, elnr, &x, &dxdxi); }; + + + void CalcElementTransformation (Point<3> xi, int elnr, + Point<3> & x) + { CalcElementTransformation (xi, elnr, &x, NULL); }; + + void CalcElementTransformation (Point<3> xi, int elnr, + Mat<3,3> & dxdxi) + { CalcElementTransformation (xi, elnr, NULL, &dxdxi); }; + + void CalcElementTransformation (Point<3> xi, int elnr, + Point<3> & x, Mat<3,3> & dxdxi) + { CalcElementTransformation (xi, elnr, &x, &dxdxi); }; + +}; + + + +// ---------------------------------------------------------------------------- +// PolynomialBasis +// ---------------------------------------------------------------------------- + +class PolynomialBasis +{ + int order; + int maxorder; + ArrayMem<double,20> f; + ArrayMem<double,20> df; + ArrayMem<double,20> ddf; + + ArrayMem<double,20> lp; + ArrayMem<double,20> dlp; + + inline void CalcLegendrePolynomials (double x); + inline void CalcDLegendrePolynomials (double x); + +public: + + PolynomialBasis () + { maxorder = -1; }; + + ~PolynomialBasis () + {}; + + void SetOrder (int aorder) + { + order = aorder; + if (order > maxorder) + { + maxorder = order; + f.SetSize(order-1); + df.SetSize(order-1); + ddf.SetSize(order-1); + lp.SetSize(order+1); + dlp.SetSize(order); + }; + }; + + inline void CalcF (double x); + inline void CalcDf (double x); + inline void CalcDDf (double x); + + inline void CalcFDf (double x); + + double GetF (int p) { return f[p-2]; }; + double GetDf (int p) { return df[p-2]; }; + double GetDDf (int p) { return ddf[p-2]; }; +}; + + + +// ---------------------------------------------------------------------------- +// BaseFiniteElement +// ---------------------------------------------------------------------------- + +template <int DIM> +class BaseFiniteElement +{ +protected: + + Point<DIM> xi; + int elnr; + const CurvedElements & curv; + const Mesh & mesh; + const MeshTopology & top; + +public: + + BaseFiniteElement(const CurvedElements & acurv) + : curv(acurv), mesh(curv.GetMesh()), top(mesh.GetTopology()) + {}; + + virtual ~BaseFiniteElement() + {}; + + void SetElementNumber (int aelnr) + { elnr = aelnr; }; // 1-based arrays in netgen + + virtual void SetReferencePoint (Point<DIM> axi) + { xi = axi; }; +}; + + + +// ---------------------------------------------------------------------------- +// BaseFiniteElement1D +// ---------------------------------------------------------------------------- + +class BaseFiniteElement1D : public BaseFiniteElement<1> +{ +protected: + PolynomialBasis b; + + int vertexnr[2]; + int edgenr; + int edgeorient; + int edgeorder; + + int maxedgeorder; + + double vshape[2]; + double vdshape[2]; + ArrayMem<double,20> eshape; + ArrayMem<double,20> edshape; + ArrayMem<double,20> eddshape; + +public: + + BaseFiniteElement1D (const CurvedElements & acurv) : BaseFiniteElement<1>(acurv) + { maxedgeorder = 1; }; + + virtual ~BaseFiniteElement1D() + {}; + + int GetVertexNr (int v) + { return vertexnr[v]; }; + + int GetEdgeNr () + { return edgenr; }; + + int GetEdgeOrder () + { return edgeorder; }; + + int GetEdgeOrientation () + { return edgeorient; }; + + void CalcVertexShapes(); + void CalcEdgeShapes(); + void CalcEdgeLaplaceShapes(); + + double GetVertexShape (int v) + { return vshape[v]; }; + + double GetEdgeShape (int index) + { return eshape[index]; }; + + double GetVertexDShape (int v) + { return vdshape[v]; }; + + double GetEdgeDShape (int index) + { return edshape[index]; }; + + double GetEdgeLaplaceShape (int index) + { return eddshape[index]; }; + +}; + + + + +// ---------------------------------------------------------------------------- +// FESegm +// ---------------------------------------------------------------------------- + +class FESegm : public BaseFiniteElement1D +{ + +public: + + FESegm(const CurvedElements & acurv) : BaseFiniteElement1D(acurv) + {}; + + virtual ~FESegm() + {}; + + void SetElementNumber (int aelnr) + { + BaseFiniteElement<1> :: SetElementNumber (aelnr); + Segment s = mesh.LineSegment(elnr); + vertexnr[0] = s.p1; + vertexnr[1] = s.p2; + edgenr = top.GetSegmentEdge(elnr); + edgeorient = top.GetSegmentEdgeOrientation(elnr); + edgeorder = curv.GetEdgeOrder(edgenr-1); // 1-based arrays in netgen + + if (edgeorder > maxedgeorder) + { + maxedgeorder = edgeorder; + eshape.SetSize(maxedgeorder-1); + edshape.SetSize(maxedgeorder-1); + eddshape.SetSize(maxedgeorder-1); + } + }; + +}; + + + +// ---------------------------------------------------------------------------- +// FEEdge +// ---------------------------------------------------------------------------- + +class FEEdge : public BaseFiniteElement1D +{ + +public: + + FEEdge(const CurvedElements & acurv) : BaseFiniteElement1D(acurv) + {}; + + virtual ~FEEdge() + {}; + + void SetElementNumber (int aelnr) + { + BaseFiniteElement<1> :: SetElementNumber (aelnr); + top.GetEdgeVertices (elnr, vertexnr[0], vertexnr[1]); + edgenr = elnr; + edgeorient = 1; + edgeorder = curv.GetEdgeOrder(edgenr-1); // 1-based arrays in netgen + + if (edgeorder > maxedgeorder) + { + maxedgeorder = edgeorder; + eshape.SetSize(maxedgeorder-1); + edshape.SetSize(maxedgeorder-1); + eddshape.SetSize(maxedgeorder-1); + } + }; + +}; + + + +// ---------------------------------------------------------------------------- +// BaseFiniteElement2D +// ---------------------------------------------------------------------------- + +class BaseFiniteElement2D : public BaseFiniteElement<2> +{ +protected: + + int nvertices; + int nedges; + + int vertexnr[4]; + int edgenr[4]; + int edgeorient[4]; + int edgeorder[4]; + int facenr; + int faceorient; + int faceorder; + + int nfaceshapes; + + int maxedgeorder; + int maxfaceorder; + + PolynomialBasis b1, b2; + + double vshape[4]; + Vec<2> vdshape[4]; + ArrayMem<double,80> eshape; + ArrayMem< Vec<2>,80> edshape; + ArrayMem<double,400> fshape; + ArrayMem<Vec<2>,400> fdshape; + ArrayMem<double,400> fddshape; + + virtual void CalcNFaceShapes () = 0; + +public: + + BaseFiniteElement2D (const CurvedElements & acurv) : BaseFiniteElement<2>(acurv) + { maxedgeorder = maxfaceorder = -1; }; + + virtual ~BaseFiniteElement2D() + {}; + + void SetElementNumber (int aelnr); + + virtual void SetVertexSingularity (int v, int exponent) = 0; + + int GetVertexNr (int v) + { return vertexnr[v]; }; + + int GetEdgeNr (int e) + { return edgenr[e]; }; + + int GetFaceNr () + { return facenr; }; + + int GetEdgeOrder (int e) + { return edgeorder[e]; }; + + int GetFaceOrder () + { return faceorder; } + + int GetNVertices () + { return nvertices; }; + + int GetNEdges () + { return nedges; }; + + int GetNFaceShapes () + { return nfaceshapes; }; + + int IsCurved () + { + bool iscurved = 0; + int e; + + for (e = 0; e < GetNEdges(); e++) + iscurved = iscurved || (GetEdgeOrder(e) > 1); + + return iscurved || (GetFaceOrder() > 1); + } + + virtual void CalcVertexShapes() = 0; + virtual void CalcEdgeShapes() = 0; + virtual void CalcFaceShapes() = 0; + + virtual void CalcFaceLaplaceShapes() = 0; + + double GetVertexShape (int v) + { return vshape[v]; }; + + double GetEdgeShape (int index) + { return eshape[index]; }; + + double GetFaceShape (int index) + { return fshape[index]; }; + + Vec<2> GetVertexDShape (int v) + { return vdshape[v]; }; + + Vec<2> GetEdgeDShape (int index) + { return edshape[index]; }; + + Vec<2> GetFaceDShape (int index) + { return fdshape[index]; }; + + double GetFaceLaplaceShape (int index) + { return fddshape[index]; }; +}; + + + +// ---------------------------------------------------------------------------- +// FETrig +// ---------------------------------------------------------------------------- + +class FETrig : public BaseFiniteElement2D +{ + Point<3> lambda; + Mat<3,2> dlambda; + + const ELEMENT_EDGE * eledge; + const ELEMENT_FACE * elface; + + virtual void CalcNFaceShapes () + { nfaceshapes = ((faceorder-1)*(faceorder-2))/2; }; + +public: + + FETrig (const CurvedElements & acurv) : BaseFiniteElement2D(acurv) + { + nvertices = 3; + nedges = 3; + eledge = MeshTopology :: GetEdges (TRIG); + elface = MeshTopology :: GetFaces (TRIG); + }; + + virtual ~FETrig() + {}; + + virtual void SetReferencePoint (Point<2> axi); + + virtual void SetVertexSingularity (int v, int exponent); + + virtual void CalcVertexShapes(); + virtual void CalcEdgeShapes(); + virtual void CalcFaceShapes(); + + virtual void CalcFaceLaplaceShapes(); +}; + + + +// ---------------------------------------------------------------------------- +// FEQuad +// ---------------------------------------------------------------------------- + +class FEQuad : public BaseFiniteElement2D +{ + const ELEMENT_FACE * elface; + + virtual void CalcNFaceShapes () + { nfaceshapes = (faceorder-1)*(faceorder-1); }; + +public: + + FEQuad (const CurvedElements & acurv) : BaseFiniteElement2D(acurv) + { + nvertices = 4; + nedges = 4; + elface = MeshTopology :: GetFaces (QUAD); + }; + + virtual ~FEQuad() + {}; + + virtual void SetVertexSingularity (int v, int exponent) + {}; + + virtual void CalcVertexShapes(); + virtual void CalcEdgeShapes(); + virtual void CalcFaceShapes(); + + virtual void CalcFaceLaplaceShapes(); +}; + + + + +// ---------------------------------------------------------------------------- +// BaseFiniteElement3D +// ---------------------------------------------------------------------------- + +class BaseFiniteElement3D : public BaseFiniteElement<3> +{ +protected: + + int nvertices; + int nedges; + int nfaces; + + int vertexnr[8]; + int edgenr[12]; + int edgeorient[12]; + int edgeorder[12]; + int facenr[6]; + int faceorient[6]; + int faceorder[6]; + int surfacenr[6]; + int surfaceorient[6]; + + int nfaceshapes[6]; + + int maxedgeorder; + int maxfaceorder; + + PolynomialBasis b1, b2; + + double vshape[8]; + Vec<3> vdshape[8]; + ArrayMem<double,120> eshape; + ArrayMem<Vec<3>,120> edshape; + ArrayMem<double,2000> fshape; + ArrayMem<Vec<3>,2000> fdshape; + + virtual void CalcNFaceShapes () = 0; + +public: + + int locmaxedgeorder; + int locmaxfaceorder; + + BaseFiniteElement3D (const CurvedElements & acurv) : BaseFiniteElement<3>(acurv) + { maxedgeorder = maxfaceorder = -1; }; + + void SetElementNumber (int aelnr); + + int GetVertexNr (int v) + { return vertexnr[v]; }; + + int GetEdgeNr (int e) + { return edgenr[e]; }; + + int GetFaceNr (int f) + { return facenr[f]; }; + + int GetNFaceShapes (int f) + { return nfaceshapes[f]; }; + + int GetEdgeOrder (int e) + { return edgeorder[e]; }; + + int GetFaceOrder (int f) + { return faceorder[f]; }; + + int GetNVertices () + { return nvertices; }; + + int GetNEdges () + { return nedges; }; + + int GetNFaces () + { return nfaces; }; + + int IsCurved () + { + bool iscurved = 0; + int e, f; + + for (e = 0; e < GetNEdges(); e++) + iscurved = iscurved || (GetEdgeOrder(e) > 1); + + for (f = 0; f < GetNFaces(); f++) + iscurved = iscurved || (GetFaceOrder(f) > 1); + + return iscurved; + } + + virtual void CalcVertexShapes() = 0; + virtual void CalcEdgeShapes() = 0; + virtual void CalcFaceShapes() = 0; + + double GetVertexShape (int v) + { return vshape[v]; }; + + double GetEdgeShape (int index) + { return eshape[index]; }; + + double GetFaceShape (int index) + { return fshape[index]; }; + + Vec<3> GetVertexDShape (int v) + { return vdshape[v]; }; + + Vec<3> GetEdgeDShape (int index) + { return edshape[index]; }; + + Vec<3> GetFaceDShape (int index) + { return fdshape[index]; }; +}; + + + +// ---------------------------------------------------------------------------- +// FETet +// ---------------------------------------------------------------------------- + +class FETet : public BaseFiniteElement3D +{ + Point<4> lambda; + Mat<4,3> dlambda; + + const ELEMENT_EDGE * eledge; + const ELEMENT_FACE * elface; + + virtual void CalcNFaceShapes () + { + for (int f = 0; f < nfaces; f++) + nfaceshapes[f] = ((faceorder[f]-1)*(faceorder[f]-2))/2; + }; + +public: + + FETet (const CurvedElements & acurv) : BaseFiniteElement3D(acurv) + { + nvertices = 4; + nedges = 6; + nfaces = 4; + eledge = MeshTopology :: GetEdges (TET); + elface = MeshTopology :: GetFaces (TET); + }; + + void SetReferencePoint (Point<3> axi); + + virtual void CalcVertexShapes(); + virtual void CalcEdgeShapes(); + virtual void CalcFaceShapes(); +}; + + + +// ---------------------------------------------------------------------------- +// FEPrism +// ---------------------------------------------------------------------------- + +class FEPrism : public BaseFiniteElement3D +{ + Point<4> lambda; // mixed barycentric coordinates + Mat<4,3> dlambda; + + const ELEMENT_EDGE * eledge; + const ELEMENT_FACE * elface; + + virtual void CalcNFaceShapes () + { + int f; + for (f = 0; f < 2; f++) + nfaceshapes[f] = ((faceorder[f]-1)*(faceorder[f]-2))/2; + for (f = 2; f < nfaces; f++) + nfaceshapes[f] = (faceorder[f]-1)*(faceorder[f]-1); + }; + +public: + + FEPrism (const CurvedElements & acurv) : BaseFiniteElement3D(acurv) + { + nvertices = 6; + nedges = 9; + nfaces = 5; + eledge = MeshTopology :: GetEdges (PRISM); + elface = MeshTopology :: GetFaces (PRISM); + }; + + void SetReferencePoint (Point<3> axi); + + virtual void CalcVertexShapes(); + virtual void CalcEdgeShapes(); + virtual void CalcFaceShapes(); +}; + + + + +// ---------------------------------------------------------------------------- +// FEPyramid +// ---------------------------------------------------------------------------- + +class FEPyramid : public BaseFiniteElement3D +{ + + const ELEMENT_EDGE * eledge; + const ELEMENT_FACE * elface; + + virtual void CalcNFaceShapes () + { + int f; + for (f = 0; f < 4; f++) + nfaceshapes[f] = ((faceorder[f]-1)*(faceorder[f]-2))/2; + for (f = 4; f < nfaces; f++) + nfaceshapes[f] = (faceorder[f]-1)*(faceorder[f]-1); + }; + +public: + + FEPyramid (const CurvedElements & acurv) : BaseFiniteElement3D(acurv) + { + nvertices = 5; + nedges = 8; + nfaces = 5; + eledge = MeshTopology :: GetEdges (PYRAMID); + elface = MeshTopology :: GetFaces (PYRAMID); + }; + + void SetReferencePoint (Point<3> axi); + + virtual void CalcVertexShapes(); + virtual void CalcEdgeShapes(); + virtual void CalcFaceShapes(); +}; + + + + +// ---------------------------------------------------------------------------- +// FEHex +// ---------------------------------------------------------------------------- + +class FEHex : public BaseFiniteElement3D +{ + + const ELEMENT_EDGE * eledge; + const ELEMENT_FACE * elface; + + virtual void CalcNFaceShapes () + { + int f; + for (f = 0; f < 6; f++) + nfaceshapes[f] = (faceorder[f]-1)*(faceorder[f]-1); + }; + +public: + + FEHex (const CurvedElements & acurv) : BaseFiniteElement3D(acurv) + { + nvertices = 8; + nedges = 12; + nfaces = 6; + eledge = MeshTopology :: GetEdges (HEX); + elface = MeshTopology :: GetFaces (HEX); + }; + + void SetReferencePoint (Point<3> axi); + + virtual void CalcVertexShapes(); + virtual void CalcEdgeShapes(); + virtual void CalcFaceShapes(); +}; + + + + +#endif diff --git a/Netgen/libsrc/meshing/curvedelems2.cpp b/Netgen/libsrc/meshing/curvedelems2.cpp new file mode 100644 index 0000000000..d01a13af79 --- /dev/null +++ b/Netgen/libsrc/meshing/curvedelems2.cpp @@ -0,0 +1,719 @@ +#include <mystdlib.h> + +#include "meshing.hpp" + +namespace netgen +{ + + +// ---------------------------------------------------------------------------- +// CurvedElements +// ---------------------------------------------------------------------------- + + CurvedElements :: CurvedElements (const Mesh & amesh) + : mesh(amesh), top(mesh.GetTopology()) + { + isHighOrder = 0; + nvisualsubsecs = 2; + nIntegrationPoints = 10; + } + + + CurvedElements :: ~CurvedElements () + { + ; + } + + + void CurvedElements :: BuildCurvedElements(Refinement * ref, int polydeg) + { + NgLock lock(const_cast<Mesh&>(mesh).Mutex(), 1); + isHighOrder = 0; + lock.UnLock(); + + const_cast<Mesh &>(mesh).UpdateTopology(); + + // set order of edges and faces + + BaseFiniteElement2D * fe2d; + + FEEdge edge (*this); + FESegm segm (*this); + FETrig trig (*this); + FEQuad quad (*this); + + int i, k, e, f; + + ARRAY<bool> edgedone; + + edgedone.SetSize (top.GetNEdges()); + + edgeorder.SetSize (top.GetNEdges()); + faceorder.SetSize (top.GetNFaces()); + + int nedgestocurve = top.GetNEdges(); + + edgedone = 0; + edgeorder = 1; + faceorder = 1; + + /* + for (e = 0; e < top.GetNEdges(); e++) + { + edgedone = 0; + edgeorder[e] = 1; + } + + for (f = 0; f < top.GetNFaces(); f++) + faceorder[f] = 1; + */ + + for (i = 1; i <= mesh.GetNSeg(); i++) + edgeorder[top.GetSegmentEdge(i)-1] = polydeg; + + + if (mesh.GetDimension() == 3) + { + for (i = 1; i <= mesh.GetNSE(); i++) + { + faceorder[top.GetSurfaceElementFace(i)-1] = polydeg; + + Element2d elem = mesh[(SurfaceElementIndex) (i-1)]; + + ARRAY<int> edgenrs; + top.GetSurfaceElementEdges(i, edgenrs); + + nedgestocurve += top.GetNEdges(elem.GetType()); + + for (int e = 0; e < top.GetNEdges(elem.GetType()); e++) + edgeorder[edgenrs[e]-1] = polydeg; + } + } + + if (polydeg == 1) + { + isHighOrder = 0; + return; + } + + PrintMessage (1, "Building curved elements, order = ", polydeg); + PushStatusF ("curving edges"); + + + + // set edgecoeffs and facecoeffs arrays index and size + + edgecoeffsindex.SetSize (top.GetNEdges()+1); + facecoeffsindex.SetSize (top.GetNFaces()+1); + + edgecoeffsindex[0] = 0; + for (e = 2; e <= top.GetNEdges()+1; e++) + edgecoeffsindex[e-1] = edgecoeffsindex[e-2] + edgeorder[e-2]-1; + + facecoeffsindex[0] = 0; + for (f = 2; f <= top.GetNFaces()+1; f++) + { + switch (top.GetFaceType (f-1)) + { + case TRIG: + facecoeffsindex[f-1] = facecoeffsindex[f-2] + + (faceorder[f-2]-1)*(faceorder[f-2]-2)/2; + break; + case QUAD: + facecoeffsindex[f-1] = facecoeffsindex[f-2] + + (faceorder[f-2]-1)*(faceorder[f-2]-1); + break; + } + } + + edgecoeffs.SetSize(edgecoeffsindex[top.GetNEdges()]); + facecoeffs.SetSize(facecoeffsindex[top.GetNFaces()]); + + + + // evaluate edge points + + PointGeomInfo newgi; // dummy variable, only needed for function call + EdgePointGeomInfo newepgi; // dummy variable, only needed for function call + Point3d xexact; // new point to be stored in ARRAY edgepts + + ARRAY<double> xi, wi; + ComputeGaussRule(nIntegrationPoints, xi, wi); + + for (i=0; i<edgecoeffsindex[top.GetNEdges()]; i++) + edgecoeffs[i] = Vec<3>(0.,0.,0.); + + + + + // all edges belonging to segments + + for (i=0; i<mesh.GetNSeg(); i++) + { + if (multithread.terminate) return; + + SetThreadPercent( double(100*i/nedgestocurve) ); + + int edgenr = top.GetSegmentEdge(i+1); + + if (edgedone[edgenr-1]) continue; + + edgedone[edgenr-1] = 1; + + Segment s = mesh.LineSegment(i+1); + + segm.SetElementNumber (i+1); + + for (k = 2; k <= segm.GetEdgeOrder(); k++) + edgecoeffs[edgecoeffsindex[edgenr-1]+k-2] = Vec<3>(0.,0.,0.); + + for (int l = 0; l < nIntegrationPoints; l++) + { + segm.SetReferencePoint (Point<1>(xi[l])); + segm.CalcVertexShapes (); + segm.CalcEdgeLaplaceShapes (); + + Point<3> xv(0,0,0); + for (int v = 0; v < 2; v++) + xv = xv + segm.GetVertexShape(v) * mesh.Point(segm.GetVertexNr(v)); + + double secpoint = xi[l]; + + if (segm.GetEdgeOrientation() == -1) secpoint = 1. - secpoint; // reverse orientation + + ref->PointBetween (mesh.Point(segm.GetVertexNr(1)), + mesh.Point(segm.GetVertexNr(0)), secpoint, + s.surfnr2, s.surfnr1, + s.epgeominfo[1], s.epgeominfo[0], + xexact, newepgi); + + for (int k = 2; k <= segm.GetEdgeOrder(); k++) + edgecoeffs[edgecoeffsindex[edgenr-1]+k-2] -= + wi[l] * segm.GetEdgeLaplaceShape(k-2) * Vec<3>(xexact - xv); + + } + + for (k = 2; k <= segm.GetEdgeOrder(); k++) + edgecoeffs[edgecoeffsindex[edgenr-1]+k-2] = + (2.0*(k-1.0)+1.0)*edgecoeffs[edgecoeffsindex[edgenr-1]+k-2]; + + } + + + + + + // all edges belonging to surface elements + + if (mesh.GetDimension() == 3) + { + for (int i=0; i<mesh.GetNSE(); i++) + { + if (multithread.terminate) return; + + SetThreadPercent( double(100*(mesh.GetNSeg()+i)/nedgestocurve) ); + Element2d elem = mesh[(SurfaceElementIndex) i]; + const ELEMENT_EDGE * eledges = MeshTopology::GetEdges(elem.GetType()); + + ARRAY<int> edgenrs; + ARRAY<int> orient; + top.GetSurfaceElementEdges(i+1, edgenrs); + top.GetSurfaceElementEdgeOrientations(i+1, orient); + + for (int e = 0; e < top.GetNEdges(elem.GetType()); e++) + { + if (edgedone[edgenrs[e]-1]) continue; + + edgedone[edgenrs[e]-1] = 1; + + edge.SetElementNumber (edgenrs[e]); + + for (k = 2; k <= edge.GetEdgeOrder(); k++) + edgecoeffs[edgecoeffsindex[edgenrs[e]-1]+k-2] = Vec<3>(0.,0.,0.); + + for (int l = 0; l < nIntegrationPoints; l++) + { + edge.SetReferencePoint (Point<1>(xi[l])); + edge.CalcVertexShapes (); + edge.CalcEdgeLaplaceShapes (); + + Point<3> xv(0,0,0); + for (int v = 0; v < 2; v++) + xv = xv + edge.GetVertexShape(v) * mesh.Point(edge.GetVertexNr(v)); + + double secpoint = xi[l]; + + ref->PointBetween (mesh.Point(edge.GetVertexNr(1)), + mesh.Point(edge.GetVertexNr(0)), secpoint, + mesh.GetFaceDescriptor(elem.GetIndex()).SurfNr(), + elem.GeomInfoPi(eledges[e][1]), + elem.GeomInfoPi(eledges[e][0]), + xexact, newgi); + + for (k = 2; k <= edge.GetEdgeOrder(); k++) + edgecoeffs[edgecoeffsindex[edgenrs[e]-1]+k-2] -= + wi[l] * edge.GetEdgeLaplaceShape(k-2) * Vec<3>(xexact - xv); + } + + for (k = 2; k <= edge.GetEdgeOrder(); k++) + edgecoeffs[edgecoeffsindex[edgenrs[e]-1]+k-2] = + (2.0*(k-1.0)+1.0)*edgecoeffs[edgecoeffsindex[edgenrs[e]-1]+k-2]; + + } + } + } + + + + +/* + + // L2-Projection for edges + + + cout << "WARNING: L2-Projection for edges" << endl; + + if (mesh.GetDimension() == 3) + { + for (int i=0; i<mesh.GetNSE(); i++) + { + Element2d elem = mesh[(SurfaceElementIndex) i]; + const ELEMENT_EDGE * eledges = MeshTopology::GetEdges(elem.GetType()); + + ARRAY<int> edgenrs; + ARRAY<int> orient; + top.GetSurfaceElementEdges(i+1, edgenrs); + top.GetSurfaceElementEdgeOrientations(i+1, orient); + + for (int e = 0; e < top.GetNEdges(elem.GetType()); e++) + { + edge.SetElementNumber (edgenrs[e]); + + int npoints = edge.GetEdgeOrder()-1; + + if (npoints == 0) continue; + + DenseMatrix mat(npoints); + DenseMatrix inv(npoints); + Vector vec[3]; + + for (int k = 0; k < 3; k++) + { + vec[k].SetSize(npoints); + for (int n = 1; n <= npoints; n++) vec[k].Set(n, 0.); + } + + for (int l = 0; l < nIntegrationPoints; l++) + { + double w = wi[l]; + + edge.SetReferencePoint (Point<1>(xi[l])); + edge.CalcVertexShapes (); + edge.CalcEdgeShapes (); + + for (int n = 0; n < npoints; n++) + for (int m = 0; m < npoints; m++) + mat.Set(n+1, m+1, mat.Get(n+1,m+1) + + edge.GetEdgeShape(n) * edge.GetEdgeShape(m) * w); + + Point<3> xv(0,0,0); + for (int v = 0; v < 2; v++) + xv = xv + edge.GetVertexShape(v) * mesh.Point(edge.GetVertexNr(v)); + + double secpoint = xi[l]; + + ref->PointBetween (mesh.Point(edge.GetVertexNr(1)), + mesh.Point(edge.GetVertexNr(0)), secpoint, + mesh.GetFaceDescriptor(elem.GetIndex()).SurfNr(), + elem.GeomInfoPi(eledges[e][1]), + elem.GeomInfoPi(eledges[e][0]), + xexact, newgi); + + for (int k = 2; k <= edge.GetEdgeOrder(); k++) + { + vec[0].Set(k-1, vec[0].Get(k-1) + Vec<3>(xexact - xv)(0)*edge.GetEdgeShape(k-2)*w ); + vec[1].Set(k-1, vec[1].Get(k-1) + Vec<3>(xexact - xv)(1)*edge.GetEdgeShape(k-2)*w ); + vec[2].Set(k-1, vec[2].Get(k-1) + Vec<3>(xexact - xv)(2)*edge.GetEdgeShape(k-2)*w ); + } + + } + + + CalcInverse(mat,inv); + + Vector a0, a1, a2; + + a0 = inv*vec[0]; + a1 = inv*vec[1]; + a2 = inv*vec[2]; + + int index = edgecoeffsindex[edge.GetEdgeNr()-1]; + + for (int n = 0; n < npoints; n++, index++) + edgecoeffs[index] = Vec<3>(a0(n+1), a1(n+1), a2(n+1)); + } + } + } + + + for (int i=0; i<mesh.GetNSeg(); i++) + { + int edgenr = top.GetSegmentEdge(i+1); + + Segment s = mesh.LineSegment(i+1); + + segm.SetElementNumber (i+1); + + int npoints = segm.GetEdgeOrder()-1; + + if (npoints == 0) continue; + + DenseMatrix mat(npoints); + DenseMatrix inv(npoints); + Vector vec[3]; + + for (int k = 0; k < 3; k++) + { + vec[k].SetSize(npoints); + for (int n = 1; n <= npoints; n++) vec[k].Set(n, 0.); + } + + for (int l = 0; l < nIntegrationPoints; l++) + { + double w = wi[l]; + + segm.SetReferencePoint (Point<1>(xi[l])); + segm.CalcVertexShapes (); + segm.CalcEdgeShapes (); + + for (int n = 0; n < npoints; n++) + for (int m = 0; m < npoints; m++) + mat.Set(n+1, m+1, mat.Get(n+1,m+1) + + segm.GetEdgeShape(n) * segm.GetEdgeShape(m) * w); + + Point<3> xv(0,0,0); + for (int v = 0; v < 2; v++) + xv = xv + segm.GetVertexShape(v) * mesh.Point(segm.GetVertexNr(v)); + + double secpoint = xi[l]; + + if (segm.GetEdgeOrientation() == -1) secpoint = 1. - secpoint; // reverse orientation + + ref->PointBetween (mesh.Point(segm.GetVertexNr(1)), + mesh.Point(segm.GetVertexNr(0)), secpoint, + s.surfnr2, s.surfnr1, + s.epgeominfo[1], s.epgeominfo[0], + xexact, newepgi); + + for (int k = 2; k <= segm.GetEdgeOrder(); k++) + { + vec[0].Set(k-1, vec[0].Get(k-1) + Vec<3>(xexact - xv)(0)*segm.GetEdgeShape(k-2)*w ); + vec[1].Set(k-1, vec[1].Get(k-1) + Vec<3>(xexact - xv)(1)*segm.GetEdgeShape(k-2)*w ); + vec[2].Set(k-1, vec[2].Get(k-1) + Vec<3>(xexact - xv)(2)*segm.GetEdgeShape(k-2)*w ); + } + + } + + + CalcInverse(mat,inv); + + Vector a0, a1, a2; + + a0 = inv*vec[0]; + a1 = inv*vec[1]; + a2 = inv*vec[2]; + + int index = edgecoeffsindex[segm.GetEdgeNr()-1]; + + for (int n = 0; n < npoints; n++, index++) + edgecoeffs[index] = Vec<3>(a0(n+1), a1(n+1), a2(n+1)); + + + + } + +*/ + + + + + + // evaluate face points + + if (mesh.GetDimension() == 3) + { + PopStatus (); + PushStatusF ("curving faces"); + + for (int j=0; j<facecoeffsindex[top.GetNFaces()]; j++) + facecoeffs[j] = Vec<3>(0.,0.,0.); + + for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) // for all surface elements + { + if (multithread.terminate) return; + + SetThreadPercent( double(100*i/mesh.GetNSE()) ); + + Element2d elem = mesh[i]; + + if (elem.GetType() == TRIG) + fe2d = &trig; + else + fe2d = &quad; + + fe2d->SetElementNumber (i+1); + + int npoints = fe2d->GetNFaceShapes(); + + if (npoints == 0) continue; + + DenseMatrix mat(npoints); + DenseMatrix inv(npoints); + Vector vec[3]; + + for (int k = 0; k < 3; k++) + { + vec[k].SetSize(npoints); + for (int n = 1; n <= npoints; n++) vec[k].Set(n, 0.); + } + + for (int j = 0; j < nIntegrationPoints; j++) + { + for (int k = 0; k < nIntegrationPoints; k++) + { + double w; + Point<2> xr; + + if (elem.GetType() == TRIG) + { + w = wi[j]*wi[k]*(1-xi[j]); + xr = Point<2> (xi[j], xi[k]*(1-xi[j])); + } + else + { + w = wi[j]*wi[k]; + xr = Point<2> (xi[j], xi[k]); + } + + fe2d->SetReferencePoint (xr); + fe2d->CalcFaceShapes (); + fe2d->CalcVertexShapes (); + fe2d->CalcEdgeShapes (); + fe2d->CalcFaceLaplaceShapes (); + + // integration over the product of the gradients of the face shapes + + for (int n = 0; n < npoints; n++) + for (int m = 0; m < npoints; m++) + mat.Set(n+1, m+1, + mat.Get(n+1,m+1) + + fe2d->GetFaceDShape(n)*fe2d->GetFaceDShape(m)*w); + + // integration over the difference between the exact geometry and the one + // defined by vertex and edge shape functions times face shape + + Point<3> xve(0.,0.,0.); + + // vertex shape functions + for (int v = 0; v < fe2d->GetNVertices(); v++) + xve = xve + fe2d->GetVertexShape(v) * mesh.Point(fe2d->GetVertexNr(v)); + + // edge shape functions + int index = 0; + for (int e = 0; e < fe2d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe2d->GetEdgeNr(e)-1]; + for (int k = 2; k <= fe2d->GetEdgeOrder(e); k++, index++, gindex++) + xve = xve + fe2d->GetEdgeShape(index) * edgecoeffs[gindex]; + } + + // exact point + + Point<3> xexact = xve; + ref->ProjectToSurface (xexact, mesh.GetFaceDescriptor(elem.GetIndex()).SurfNr()); + + Vec<3> v2 = w*(Vec<3>(xexact)-Vec<3>(xve)); + + for (int k = 0; k < 3; k++) + for (int n = 0; n < npoints; n++) + vec[k].Set(n+1, vec[k].Get(n+1) - fe2d->GetFaceLaplaceShape(n)*v2(k)); + } + } + + CalcInverse(mat,inv); + + Vector a0(npoints), a1(npoints), a2(npoints); + + /* + a0 = inv*vec[0]; + a1 = inv*vec[1]; + a2 = inv*vec[2]; + */ + inv.Mult (vec[0], a0); + inv.Mult (vec[1], a1); + inv.Mult (vec[2], a2); + + int index = facecoeffsindex[fe2d->GetFaceNr()-1]; + + for (int n = 0; n < npoints; n++, index++) + facecoeffs[index] = Vec<3>(a0.Elem(n+1), a1.Elem(n+1), a2.Elem(n+1)); + } + } + + + + +/* + cout << "WARNING: L2-Projection for faces" << endl; + + // evaluate face points + + if (mesh.GetDimension() == 3) + { + for (int i=0; i<facecoeffsindex[top.GetNFaces()]; i++) + facecoeffs[i] = Vec<3>(0.,0.,0.); + + for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) // for all surface elements + { + Element2d elem = mesh[i]; + + if (elem.GetType() == TRIG) + fe2d = &trig; + else + fe2d = &quad; + + fe2d->SetElementNumber (i+1); + + int npoints = fe2d->GetNFaceShapes(); + + if (npoints == 0) continue; + + DenseMatrix mat(npoints); + DenseMatrix inv(npoints); + Vector vec[3]; + + for (int k = 0; k < 3; k++) + { + vec[k].SetSize(npoints); + for (int n = 1; n <= npoints; n++) vec[k].Set(n, 0.); + } + + for (int j = 0; j < nIntegrationPoints; j++) + { + for (int k = 0; k < nIntegrationPoints; k++) + { + double w; + Point<2> xr; + + if (elem.GetType() == TRIG) + { + w = wi[j]*wi[k]*(1-xi[j]); + xr = Point<2> (xi[j], xi[k]*(1-xi[j])); + } + else + { + w = wi[j]*wi[k]; + xr = Point<2> (xi[j], xi[k]); + } + + fe2d->SetReferencePoint (xr); +// fe2d->CalcFaceDShape (false, true); + fe2d->CalcFaceShapes (); + + // integration over the product of the gradients of the face shapes + + for (int n = 0; n < npoints; n++) + for (int m = 0; m < npoints; m++) + mat.Set(n+1, m+1, mat.Get(n+1,m+1) + + fe2d->GetFaceShape(n)*fe2d->GetFaceShape(m)*w); + + // integration over the difference between the exact geometry and the one + // defined by vertex and edge shape functions times face shape + + Point<3> xve(0.,0.,0.); + + // vertex shape functions + fe2d->CalcVertexShapes (); +// fe2d->CalcVertexShape (true, false); + for (int v = 0; v < fe2d->GetNVertices(); v++) + xve = xve + fe2d->GetVertexShape(v) * mesh.Point(fe2d->GetVertexNr(v)); + + // edge shape functions +// fe2d->CalcEdgeShape (true, false); + fe2d->CalcEdgeShapes (); + + int index = 0; + for (int e = 0; e < fe2d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe2d->GetEdgeNr(e)-1]; + + for (int k = 2; k <= fe2d->GetEdgeOrder(e); k++, index++, gindex++) + xve = xve + fe2d->GetEdgeShape(index) * edgecoeffs[gindex]; + } + + // exact point + + Point<3> xexact = xve; + ref->ProjectToSurface (xexact, mesh.GetFaceDescriptor(elem.GetIndex()).SurfNr()); + + Vec<3> v = w*(Vec<3>(xexact)-Vec<3>(xve)); + + fe2d->CalcFaceLaplaceShapes (); + + for (int k = 0; k < 3; k++) + for (int n = 0; n < npoints; n++) + vec[k].Set(n+1, vec[k].Get(n+1) + fe2d->GetFaceShape(n)*v(k)); + } + } + + CalcInverse(mat,inv); + + Vector a0, a1, a2; + + a0 = inv*vec[0]; + a1 = inv*vec[1]; + a2 = inv*vec[2]; + + int index = facecoeffsindex[fe2d->GetFaceNr()-1]; + + for (int n = 0; n < npoints; n++, index++) + facecoeffs[index] = Vec<3>(a0(n+1), a1(n+1), a2(n+1)); + } + } +*/ + + + PrintMessage (5, "reducing order"); + + for (e = 0; e < top.GetNEdges(); e++) + if (edgeorder[e] > 1) + { + int i; + double maxcoeff = 0.; + + for (i = edgecoeffsindex[e]; i < edgecoeffsindex[e+1]; i++) + maxcoeff = max2 (maxcoeff, edgecoeffs[i].Length()); + + if (maxcoeff < 1e-12) edgeorder[e] = 1; + } + + for (f = 0; f < top.GetNFaces(); f++) + if (faceorder[f] > 1) + { + int i; + double maxcoeff = 0.; + + for (i = facecoeffsindex[f]; i < facecoeffsindex[f+1]; i++) + maxcoeff = max2 (maxcoeff, facecoeffs[i].Length()); + + if (maxcoeff < 1e-12) faceorder[f] = 1; + } + + isHighOrder = 1; // true + + PrintMessage(1, "done"); + PopStatus(); + // cout << "finished" << endl; + } + +} // namespace netgen diff --git a/Netgen/libsrc/meshing/delaunay.cpp b/Netgen/libsrc/meshing/delaunay.cpp new file mode 100644 index 0000000000..8e44c5f739 --- /dev/null +++ b/Netgen/libsrc/meshing/delaunay.cpp @@ -0,0 +1,1652 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +// #define TEST +// #define TEST2 + +namespace netgen +{ + 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 & PNum(int i) { return pnums[i-1]; } + PointIndex PNum(int i) const { return pnums[i-1]; } + + PointIndex & operator[] (int i) { return pnums[i]; } + PointIndex operator[] (int i) const { return pnums[i]; } + + int & NB(int i) { return nb[i-1]; } + int NB(int i) const { return nb[i-1]; } + + inline void GetFace (int i, INDEX_3 & face) const; + inline int FaceNr (INDEX_3 & face) const; // which face nr is it ? + inline void GetFace (int i, Element2d & face) const; + }; + + + + inline int DelaunayTet :: FaceNr (INDEX_3 & face) const + { + for (int i = 0; i < 3; i++) + if (pnums[i] != face.I1() && + pnums[i] != face.I2() && + pnums[i] != face.I3()) + return i+1; + return 4; + } + + static const int deltetfaces[][3] = + { { 2, 3, 4 }, + { 3, 1, 4 }, + { 1, 2, 4 }, + { 2, 1, 3 } }; + + + inline void DelaunayTet :: GetFace (int i, INDEX_3 & face) const + { + face.I(1) = PNum(deltetfaces[i-1][0]); + face.I(2) = PNum(deltetfaces[i-1][1]); + face.I(3) = PNum(deltetfaces[i-1][2]); + } + + inline void DelaunayTet :: GetFace (int i, Element2d & face) const + { + face.SetType(TRIG); + face[0] = PNum(deltetfaces[i-1][0]); + face[1] = PNum(deltetfaces[i-1][1]); + face[2] = PNum(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); + + // get neighbour of element elnr in direction fnr + int GetNB (int elnr, int fnr) + { return tets.Get(elnr).NB(fnr); } + + // + void ResetFaceHT (int size) + { + faces.SetSize (size); + } + + void PrintMemInfo (ostream & ost) const; + }; + + + + void MeshNB :: Add (int elnr) + { + INDEX_3 i3, i32; + + DelaunayTet & el = tets.Elem(elnr); + + for (int i = 1; i <= 4; i++) + { + el.GetFace (i, i3); + i3.Sort(); + + int bnr, posnr, othertet; + + if (!faces.PositionCreate (i3, posnr)) + { + // face already in use + faces.GetData (posnr, othertet); + + 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; + } + } + } + + + void MeshNB :: Delete (int elnr) + { + INDEX_3 i3; + DelaunayTet & el = tets.Elem(elnr); + + for (int i = 1; i <= 4; i++) + { + el.GetFace (i, i3); + i3.Sort(); + faces.Set (i3, el.NB(i)); + } + } + + + void MeshNB :: PrintMemInfo (ostream & ost) const + { + /* + int uf = 0; + for (int i = 1; i <= face2el.Size(); i++) + if (face2el.Get(i).I1()) + uf++; + + ost << "MeshNB: " + << "validels = " << validels << " totels = " << el2face.Size() << endl + << "validfaces = " << uf << " totfaces = " << face2el.Size() << endl + << "face2el: " << face2el.Size() * sizeof(INDEX_2) << endl + << "el2face: " << el2face.Size() * sizeof(INDEX_4) << endl; + */ + } + + + + + + /* + connected lists of cosphereical elements + */ + class SphereList + { + ARRAY<int> links; + public: + SphereList () { ; } + inline void AddElement (int elnr); + inline void DeleteElement (int elnr); + inline void ConnectElement (int eli, int toi); + void GetList (int eli, ARRAY<int> & linked) const; + }; + + inline void SphereList :: AddElement (int elnr) + { + if (elnr > links.Size()) + links.Append (1); + links.Elem(elnr) = elnr; + } + + inline void SphereList :: DeleteElement (int elnr) + { + links.Elem(elnr) = 0; + } + + inline void SphereList :: ConnectElement (int eli, int toi) + { + links.Elem (eli) = links.Get (toi); + links.Elem (toi) = eli; + } + + 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<Point3d> & centers, ARRAY<double> & radi2, + ARRAY<int> & connected, ARRAY<int> & treesearch, + ARRAY<int> & freelist, SphereList & list, + IndexSet & insphere, IndexSet & closesphere) + { + int i, j, k, l; + +#ifdef TEST2 + (*testout) << endl << "add point " << newp << endl; +#endif + + /* + find any sphere, such that newp is contained in + */ + + DelaunayTet el; + int cfelind = -1; + + const Point3d * pp[4]; + Point3d pc; + double r2; + Point3d tpmin, tpmax; + + tettree.GetIntersecting (newp, newp, treesearch); + for (j = 0; j < treesearch.Size(); j++) + { + int jjj = treesearch[j]; + if (Dist2 (centers.Get(jjj), newp) < radi2.Get(jjj)) + { + el = tempels.Get(jjj); + cfelind = jjj; + break; + } + } + + /* + 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.Array().Size()+1; + + // if point in sphere, then it is also closesphere + for (j = starti; j < nstarti; j++) + { + int helind = insphere.Array().Get(j); + if (!closesphere.IsIn (helind)) + closesphere.Add (helind); + } + + // add connected spheres to insphere - list + for (j = starti; j < nstarti; j++) + { + list.GetList (insphere.Array().Get(j), connected); + for (k = 1; k <= connected.Size(); k++) + { + int celind = connected.Get(k); + + if (tempels.Get(celind).PNum(1) != -1 && + !insphere.IsIn (celind)) + { + changed = 1; + insphere.Add (celind); + } + } + } + + // check neighbour-tets + for (j = starti; j < nstarti; j++) + for (k = 1; k <= 4; k++) + { + int helind = insphere.Array().Get(j); + int nbind = meshnb.GetNB (helind, k); + + if (nbind && !insphere.IsIn (nbind) ) + { + 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.PNum(2)); + const Point3d & p3 = mesh.Point (face.PNum(3)); + + 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).PNum(k))) > 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; + + for (j = 1; j <= insphere.Array().Size(); j++) + for (k = 1; k <= 4; k++) + { + // int elind = insphere.Array().Get(j); + int celind = insphere.Array().Get(j); + int nbind = meshnb.GetNB (celind, k); + + if (!nbind || !insphere.IsIn (nbind)) + { + Element2d face; + tempels.Get (celind).GetFace (k, face); + + Element newel(4); + for (l = 1; l <= 3; l++) + newel.PNum(l) = face.PNum(l); + newel.PNum(4) = newpi; + + newels.Append (newel); + + Vec3d v1(mesh.Point (face.PNum(1)), mesh.Point (face.PNum(2))); + Vec3d v2(mesh.Point (face.PNum(1)), mesh.Point (face.PNum(3))); + Vec3d n = Cross (v1, v2); + n /= n.Length(); + if (n * Vec3d(mesh.Point (face.PNum(1)), + mesh.Point (tempels.Get(insphere.Array().Get(j)).PNum(k))) + > 0) + n *= -1; + + double hval = n * Vec3d (mesh.Point (face.PNum(1)), newp); + + 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.PNum(1)) << " " + << mesh.Point (face.PNum(2)) << " " + << mesh.Point (face.PNum(3)) << endl; + } + } + } + + meshnb.ResetFaceHT (10*insphere.Array().Size()+1); + + for (j = 1; j <= insphere.Array().Size(); j++) + { + // int elind = + int celind = insphere.Array().Get(j); + + meshnb.Delete (celind); + list.DeleteElement (celind); + + for (k = 1; k <= 4; k++) + tempels.Elem(celind).PNum(k) = -1; + + ((ADTree6&)tettree.Tree()).DeleteElement (celind); + freelist.Append (celind); + } + + + int hasclose = 0; + for (j = 1; j <= closesphere.Array().Size(); j++) + { + int ind = closesphere.Array().Get(j); + if (!insphere.IsIn(ind) && + fabs (Dist2 (centers.Get (ind), newp) - radi2.Get(ind)) < 1e-8 ) + hasclose = 1; + } + + for (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 (k = 1; k <= 4; k++) + pp[k-1] = &mesh.Point (newels.Get(j).PNum(k)); + + if (CalcSphereCenter (&pp[0], pc) ) + { + PrintSysError ("Delaunay: New tet is flat"); + + (*testout) << "new tet is flat" << endl; + for (k = 1; k <= 4; k++) + (*testout) << newels.Get(j).PNum(k) << " "; + (*testout) << endl; + for (k = 1; k <= 4; k++) + (*testout) << *pp[k-1] << " "; + (*testout) << endl; + } + + r2 = Dist2 (*pp[0], pc); + if (hasclose) + for (k = 1; k <= closesphere.Array().Size(); k++) + { + int csameind = closesphere.Array().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 (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, l; + const Point3d * pp[4]; + + ARRAY<Point3d> centers; + ARRAY<double> radi2; + + Point3d tpmin, tpmax; + + + // new: local box + mesh.GetBox (pmax, pmin); + for (i = 1; i <= adfront->GetNF(); i++) + { + const Element2d & face = adfront->GetFace(i); + for (j = 0; j < face.GetNP(); j++) + { + pmin.SetToMin (mesh.Point (face[j])); + pmax.SetToMax (mesh.Point (face[j])); + } + } + + + 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.PNum(1) = mesh.AddPoint (cp1); + startel.PNum(2) = mesh.AddPoint (cp2); + startel.PNum(3) = mesh.AddPoint (cp3); + startel.PNum(4) = mesh.AddPoint (cp4); + + // flag points to use for Delaunay: + BitArrayChar<PointIndex::BASE> usep(np); + usep.Clear(); + for (i = 1; i <= adfront->GetNF(); i++) + { + const Element2d & 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.PNum(1)); + for (k = 2; k <= 4; k++) + { + tpmin.SetToMin (mesh.Point (startel.PNum(k))); + tpmax.SetToMax (mesh.Point (startel.PNum(k))); + } + tpmax = tpmax + 0.01 * (tpmax - tpmin); + tettree.Insert (tpmin, tpmax, 1); + + + Point3d pc; + + for (k = 1; k <= 4; k++) + pp[k-1] = &mesh.Point (startel.PNum(k)); + + CalcSphereCenter (&pp[0], pc); + + centers.Append (pc); + radi2.Append (Dist2 (*pp[0], pc)); + + + IndexSet insphere(mesh.GetNP()); + IndexSet closesphere(mesh.GetNP()); + + + +#ifdef MARK + MARK (delaunay1); +#endif + + + // "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 % 100 == 0) + 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); + } + +#ifdef MARK + MARK (delaunay3); +#endif + + + + for (i = tempels.Size(); i >= 1; i--) + if (tempels.Get(i).PNum(1) <= 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, const MeshingParameters & mp) + { + PointIndex pi; + int i, j, k, l; + int ii; + int np, ne; + + PrintMessage (1, "Delaunay meshing"); + PrintMessage (3, "number of points: ", mesh.GetNP()); + PushStatus ("Delaunay meshing"); + + + + ARRAY<DelaunayTet> tempels; + + Point3d pmin, pmax; + Point3d tpmin, tpmax; + const Point3d * pp[4]; + + + 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 (pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) + tempmesh.AddPoint (mesh[pi]); + + for (i = 1; i <= tempels.Size(); i++) + { + Element el(4); + for (j = 1; j <= 4; j++) + el.PNum(j) = tempels.Elem(i).PNum(j); + + el.SetIndex (1); + 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)); + 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.PNum(3), el.PNum(4)); + + tempmesh.AddVolumeElement (el); + } + + MeshQuality3d (tempmesh); + + for (i = 1; i <= mesh.GetNOpenElements(); i++) + { + Element2d sel = mesh.OpenElement(i); + sel.SetIndex(1); + tempmesh.AddSurfaceElement (sel); + Swap (sel.PNum(2), sel.PNum(3)); + tempmesh.AddSurfaceElement (sel); + } + + + for (i = 1; i <= 4; i++) + { + Element2d self(3); + self.SetIndex (1); + startel.GetFace (i, self); + tempmesh.AddSurfaceElement (self); + } + + + tempmesh.AddFaceDescriptor (FaceDescriptor (1, 1, 0, 0)); + tempmesh.AddFaceDescriptor (FaceDescriptor (2, 1, 0, 0)); + + + // for (i = mesh.GetNP() - 3; i <= mesh.GetNP(); i++) + // tempmesh.AddLockedPoint (i); + for (pi = PointIndex::BASE; + pi < tempmesh.GetNP() + PointIndex::BASE; pi++) + tempmesh.AddLockedPoint (pi); + + // tempmesh.PrintMemInfo(cout); + // tempmesh.Save ("tempmesh.vol"); + + for (i = 1; i <= 2; i++) + { + tempmesh.FindOpenElements (); + + PrintMessage (5, "Num open: ", tempmesh.GetNOpenElements()); + tempmesh.CalcSurfacesOfNode (); + + tempmesh.FreeOpenElementsEnvironment (1); + + MeshOptimize3d meshopt; + meshopt.SwapImprove(tempmesh, OPT_CONFORM); + } + + +#ifdef STAT_STREAM + tempmesh.FindOpenElements (); + PrintMessage (5, "Num open: ", tempmesh.GetNOpenElements()); + (*statout) << tempmesh.GetNOpenElements() << " & " << endl; +#endif + + MeshQuality3d (tempmesh); + + tempels.SetSize(0); + for (i = 1; i <= tempmesh.GetNE(); i++) + tempels.Append (tempmesh.VolumeElement(i)); + } + + + + + // remove degenerated + + BitArray badnode(mesh.GetNP()); + badnode.Clear(); + int ndeg = 0; + for (i = 1; i <= tempels.Size(); i++) + { + Element el(4); + for (j = 1; j <= 4; j++) + el.PNum(j) = tempels.Elem(i).PNum(j); + // Element & el = tempels.Elem(i); + 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)); + 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.PNum(1) <= np && el.PNum(2) <= np && + el.PNum(3) <= np && el.PNum(4) <= np) ) // old: 1e-12 + { + badnode.Set(el.PNum(1)); + badnode.Set(el.PNum(2)); + badnode.Set(el.PNum(3)); + badnode.Set(el.PNum(4)); + ndeg++; + (*testout) << "vol = " << vol << " h = " << h << endl; + } + + if (vol > 0) + Swap (el.PNum(3), el.PNum(4)); + } + + ne = tempels.Size(); + for (i = ne; i >= 1; i--) + { + const DelaunayTet & el = tempels.Get(i); + if (badnode.Test(el.PNum(1)) || + badnode.Test(el.PNum(2)) || + badnode.Test(el.PNum(3)) || + badnode.Test(el.PNum(4)) ) + 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 (i = 1; i <= mesh.GetNOpenElements(); i++) + { + const Element2d & tri = mesh.OpenElement(i); + INDEX_3 i3(tri.PNum(1), tri.PNum(2), tri.PNum(3)); + i3.Sort(); + openeltab.Set (i3, i); + } + + for (i = 1; i <= tempels.Size(); i++) + { + for (j = 1; j <= 4; j++) + { + Element2d face; + tempels.Get(i).GetFace (j, face); + INDEX_3 i3(face.PNum(1), face.PNum(2), face.PNum(3)); + i3.Sort(); + if (openeltab.Used(i3)) + openeltab.Set (i3, 0); + } + } + + // and store them in openels + for (i = 1; i <= openeltab.GetNBags(); i++) + for (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 (ii = 1; ii <= openels.Size(); ii++) + { + i = openels.Get(ii); + const Element2d & el = mesh.OpenElement(i); + for (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 (i = 1; i <= tempels.Size(); i++) + { + const DelaunayTet & el = tempels.Get(i); + INDEX_2 i2; + for (j = 1; j <= 6; j++) + { + switch (j) + { + case 1: i2 = INDEX_2(el.PNum(1), el.PNum(2)); break; + case 2: i2 = INDEX_2(el.PNum(1), el.PNum(3)); break; + case 3: i2 = INDEX_2(el.PNum(1), el.PNum(4)); break; + case 4: i2 = INDEX_2(el.PNum(2), el.PNum(3)); break; + case 5: i2 = INDEX_2(el.PNum(2), el.PNum(4)); break; + case 6: i2 = INDEX_2(el.PNum(3), el.PNum(4)); break; + } + i2.Sort(); + tetedges.Set (i2, 1); + } + } + // cout << "tetedges:"; + // tetedges.PrintMemInfo (cout); + + 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 (i = ne; i >= 1; i--) + { + const DelaunayTet & el = tempels.Get(i); + if (badnode.Test(el.PNum(1)) || + badnode.Test(el.PNum(2)) || + badnode.Test(el.PNum(3)) || + badnode.Test(el.PNum(4)) ) + 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 (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.PNum(1))); + Point3d ltpmax (tpmin); + + for (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 (i = 1; i <= tempels.Size(); i++) + { + // const Point3d *pp[4]; + int tetpi[4]; + DelaunayTet & el = tempels.Elem(i); + + int intersect = 0; + + for (j = 1; j <= 4; j++) + { + pp[j-1] = &mesh.Point(el.PNum(j)); + tetpi[j-1] = el.PNum(j); + } + + Point3d tetpmin(*pp[0]); + Point3d tetpmax(tetpmin); + for (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++) + { + j = neartrias.Get(jj); + + const Element2d & tri = mesh.OpenElement(j); + const Point3d *tripp[3]; + int tripi[3]; + + for (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--; + } + } + } + + +#ifdef MARK + MARK (delaunay4); +#endif + + + + + + + + + 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 (i = 1; i <= mesh.GetNOpenElements(); i++) + { + const Element2d & tri = mesh.OpenElement(i); + INDEX_3 i3 (tri.PNum(1), tri.PNum(2), tri.PNum(3)); + i3.Sort(); + boundaryfaces.PrepareSet (i3); + } + boundaryfaces.AllocateElements(); + for (i = 1; i <= mesh.GetNOpenElements(); i++) + { + const Element2d & tri = mesh.OpenElement(i); + INDEX_3 i3 (tri.PNum(1), tri.PNum(2), tri.PNum(3)); + i3.Sort(); + boundaryfaces.Set (i3, 1); + } + + for (i = 1; i <= tempels.Size(); i++) + for (j = 1; j <= 4; j++) + tempels.Elem(i).NB(j) = 0; + + TABLE<int,PointIndex::BASE> elsonpoint(mesh.GetNP()); + for (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 (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(3); + for (pi = PointIndex::BASE; + pi < mesh.GetNP()+PointIndex::BASE; pi++) + { + faceht.SetSize (4 * elsonpoint[pi].Size()); + for (ii = 0; ii < elsonpoint[pi].Size(); ii++) + { + i = elsonpoint[pi][ii]; + const DelaunayTet & el = tempels.Get(i); + + for (j = 1; j <= 4; j++) + { + el.GetFace (j, hel); + hel.Invert(); + hel.NormalizeNumbering(); + + if (hel.PNum(1) == pi) + { + INDEX_3 i3(hel.PNum(1), hel.PNum(2), hel.PNum(3)); + + if (!boundaryfaces.Used (i3)) + { + if (faceht.Used (i3)) + { + INDEX_2 i2 = faceht.Get(i3); + + tempels.Elem(i).NB(j) = i2.I1(); + tempels.Elem(i2.I1()).NB(i2.I2()) = i; + } + else + { + hel.Invert(); + hel.NormalizeNumbering(); + INDEX_3 i3(hel.PNum(1), hel.PNum(2), hel.PNum(3)); + INDEX_2 i2(i, j); + faceht.Set (i3, 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.GetFace (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).NB(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; + + 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.PNum(1)); + const Point3d & p2 = mesh.Point (el.PNum(2)); + const Point3d & p3 = mesh.Point (el.PNum(3)); + const Point3d & p4 = mesh.Point (el.PNum(4)); + + 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 (j = 1; j <= 4; j++) + { + INDEX_3 i3; + Element2d face; + tempels.Get(ei).GetFace(j, face); + for (int kk = 1; kk <= 3; kk++) + i3.I(kk) = face.PNum(kk); + i3.Sort(); + + + if (tempels.Get(ei).NB(j)) + elstack.Append (tempels.Get(ei).NB(j)); + + /* + if (innerfaces.Used(i3)) + { + INDEX_2 i2 = innerfaces.Get(i3); + int other = i2.I1() + i2.I2() - ei; + + if (other != tempels.Get(ei).NB(j)) + cerr << "different1 !!" << endl; + + if (other) + { + elstack.Append (other); + } + } + else + if (tempels.Get(ei).NB(j)) + cerr << "different2 !!" << endl; + */ + + } + } + } + } + + + + // check outer elements + if (debugparam.slowchecks) + { + for (i = 1; i <= ne; i++) + { + const DelaunayTet & el = tempels.Get(i); + const Point3d & p1 = mesh.Point (el.PNum(1)); + const Point3d & p2 = mesh.Point (el.PNum(2)); + const Point3d & p3 = mesh.Point (el.PNum(3)); + const Point3d & p4 = mesh.Point (el.PNum(4)); + + 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 (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 (i = ne; i >= 1; i--) + { + if (outer.Test(i)) + tempels.DeleteElement(i); + } + + + // (*mycout) << "done" << endl; + + + // mesh.points.SetSize(mesh.points.Size()-4); + + for (i = 1; i <= tempels.Size(); i++) + { + Element el(4); + for (j = 1; j <= 4; j++) + el.PNum(j) = tempels.Elem(i).PNum(j); + mesh.AddVolumeElement (el); + } + + PrintMessage (5, "outer removed"); + + mesh.FindOpenElements(); + + mesh.Compress(); + + PopStatus (); + } +} diff --git a/Netgen/libsrc/meshing/findip.cpp b/Netgen/libsrc/meshing/findip.cpp new file mode 100644 index 0000000000..7be0ee913d --- /dev/null +++ b/Netgen/libsrc/meshing/findip.cpp @@ -0,0 +1,115 @@ +// find inner point + +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + + +template <typename POINTARRAY, typename FACEARRAY> +int FindInnerPoint (POINTARRAY & points, + FACEARRAY & faces, + Point3d & p) +{ + int i, j; + ARRAY<Vec3d> a; + ARRAY<double> c; + Point3d p1, pmin; + int i1, i2, i3, i4; + int nf; + DenseMatrix m(3), inv(3); + Vector rs(3), x(3); + double f, fmin, hd, hmax; + + nf = faces.Size(); + + // testout << "#faces = " << faces.Size() << endl; + // testout << "#points = " << points.Size() << endl; + + a.SetSize (nf); + c.SetSize (nf); + + for (i = 1; i <= nf; i++) + { + p1 = points.Get(faces.Get(i).PNum(1)); + a.Elem(i) = Cross (points.Get(faces.Get(i).PNum(2)) - points.Get(faces.Get(i).PNum(1)), + points.Get(faces.Get(i).PNum(3)) - points.Get(faces.Get(i).PNum(1))); + a.Elem(i) /= a.Get(i).Length(); + c.Elem(i) = - (a.Get(i).X() * p1.X() + a.Get(i).Y() * p1.Y() + a.Get(i).Z() * p1.Z()); + } + + + hmax = 0; + for (i = 1; i <= nf; i++) + { + const Element2d & el = faces.Get(i); + for (j = 1; j <= 3; j++) + { + double hi = Dist (points.Get(el.PNumMod(j)), + points.Get(el.PNumMod(j+1))); + if (hi > hmax) hmax = hi; + } + } + + + fmin = 100; + pmin = Point3d (0, 0, 0); + + for (i1 = 1; i1 <= nf; i1++) + for (i2 = i1+1; i2 <= nf; i2++) + for (i3 = i2+1; i3 <= nf; i3++) + for (i4 = i3+1; i4 <= nf; i4++) + { + m.Elem(1, 1) = a.Get(i1).X() - a.Get(i2).X(); + m.Elem(1, 2) = a.Get(i1).Y() - a.Get(i2).Y(); + m.Elem(1, 3) = a.Get(i1).Z() - a.Get(i2).Z(); + rs.Elem(1) = c.Get(i2) - c.Get(i1); + + m.Elem(2, 1) = a.Get(i1).X() - a.Get(i3).X(); + m.Elem(2, 2) = a.Get(i1).Y() - a.Get(i3).Y(); + m.Elem(2, 3) = a.Get(i1).Z() - a.Get(i3).Z(); + rs.Elem(2) = c.Get(i3) - c.Get(i1); + + m.Elem(3, 1) = a.Get(i1).X() - a.Get(i4).X(); + m.Elem(3, 2) = a.Get(i1).Y() - a.Get(i4).Y(); + m.Elem(3, 3) = a.Get(i1).Z() - a.Get(i4).Z(); + rs.Elem(3) = c.Get(i4) - c.Get(i1); + + + if (fabs (m.Det()) > 1e-10) + { + CalcInverse (m, inv); + inv.Mult (rs, x); + + // testout << "x = " << x << endl; + + + f = -1e10; + for (i = 1; i <= nf; i++) + { + hd = x.Elem(1) * a.Get(i).X() + + x.Elem(2) * a.Get(i).Y() + + x.Elem(3) * a.Get(i).Z() + + c.Get(i); + if (hd > f) f = hd; + } + + if (f < fmin) + { + fmin = f; + pmin.X() = x.Elem(1); + pmin.Y() = x.Elem(2); + pmin.Z() = x.Elem(3); + } + } + } + + // testout << "fmin = " << fmin << endl; + // testout << "pmin = " << pmin << endl; + + p = pmin; + return (fmin < -1e-3 * hmax) ? 1 : 0; + // return (fmin < 0) ? 1 : 0; +} +} diff --git a/Netgen/libsrc/meshing/findip.hpp b/Netgen/libsrc/meshing/findip.hpp new file mode 100644 index 0000000000..b47c3ac6dc --- /dev/null +++ b/Netgen/libsrc/meshing/findip.hpp @@ -0,0 +1,116 @@ +/* +// find inner point + +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ +*/ + +template <typename POINTARRAY, typename FACEARRAY> +inline int FindInnerPoint (POINTARRAY & points, + FACEARRAY & faces, + Point3d & p) +{ + int i, j; + ARRAY<Vec3d> a; + ARRAY<double> c; + Point3d p1, pmin; + int i1, i2, i3, i4; + int nf; + DenseMatrix m(3), inv(3); + Vector rs(3), x(3); + double f, fmin, hd, hmax; + + nf = faces.Size(); + + // testout << "#faces = " << faces.Size() << endl; + // testout << "#points = " << points.Size() << endl; + + a.SetSize (nf); + c.SetSize (nf); + + for (i = 1; i <= nf; i++) + { + p1 = points.Get(faces.Get(i).PNum(1)); + a.Elem(i) = Cross (points.Get(faces.Get(i).PNum(2)) - points.Get(faces.Get(i).PNum(1)), + points.Get(faces.Get(i).PNum(3)) - points.Get(faces.Get(i).PNum(1))); + a.Elem(i) /= a.Get(i).Length(); + c.Elem(i) = - (a.Get(i).X() * p1.X() + a.Get(i).Y() * p1.Y() + a.Get(i).Z() * p1.Z()); + } + + + hmax = 0; + for (i = 1; i <= nf; i++) + { + const Element2d & el = faces.Get(i); + for (j = 1; j <= 3; j++) + { + double hi = Dist (points.Get(el.PNumMod(j)), + points.Get(el.PNumMod(j+1))); + if (hi > hmax) hmax = hi; + } + } + + + fmin = 100; + pmin = Point3d (0, 0, 0); + + for (i1 = 1; i1 <= nf; i1++) + for (i2 = i1+1; i2 <= nf; i2++) + for (i3 = i2+1; i3 <= nf; i3++) + for (i4 = i3+1; i4 <= nf; i4++) + { + m.Elem(1, 1) = a.Get(i1).X() - a.Get(i2).X(); + m.Elem(1, 2) = a.Get(i1).Y() - a.Get(i2).Y(); + m.Elem(1, 3) = a.Get(i1).Z() - a.Get(i2).Z(); + rs.Elem(1) = c.Get(i2) - c.Get(i1); + + m.Elem(2, 1) = a.Get(i1).X() - a.Get(i3).X(); + m.Elem(2, 2) = a.Get(i1).Y() - a.Get(i3).Y(); + m.Elem(2, 3) = a.Get(i1).Z() - a.Get(i3).Z(); + rs.Elem(2) = c.Get(i3) - c.Get(i1); + + m.Elem(3, 1) = a.Get(i1).X() - a.Get(i4).X(); + m.Elem(3, 2) = a.Get(i1).Y() - a.Get(i4).Y(); + m.Elem(3, 3) = a.Get(i1).Z() - a.Get(i4).Z(); + rs.Elem(3) = c.Get(i4) - c.Get(i1); + + + if (fabs (m.Det()) > 1e-10) + { + CalcInverse (m, inv); + inv.Mult (rs, x); + + // testout << "x = " << x << endl; + + + f = -1e10; + for (i = 1; i <= nf; i++) + { + hd = x.Elem(1) * a.Get(i).X() + + x.Elem(2) * a.Get(i).Y() + + x.Elem(3) * a.Get(i).Z() + + c.Get(i); + if (hd > f) f = hd; + } + + if (f < fmin) + { + fmin = f; + pmin.X() = x.Elem(1); + pmin.Y() = x.Elem(2); + pmin.Z() = x.Elem(3); + } + } + } + + // testout << "fmin = " << fmin << endl; + // testout << "pmin = " << pmin << endl; + + p = pmin; + return (fmin < -1e-3 * hmax) ? 1 : 0; + // return (fmin < 0) ? 1 : 0; +} + diff --git a/Netgen/libsrc/meshing/geomsearch.cpp b/Netgen/libsrc/meshing/geomsearch.cpp new file mode 100644 index 0000000000..53c04e12ac --- /dev/null +++ b/Netgen/libsrc/meshing/geomsearch.cpp @@ -0,0 +1,265 @@ +#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 = 1; i <= size.i1*size.i2*size.i3; i++) + { + delete hashtable.Get(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 Element2d& elem) +{ + maxp.X()=points->Get(elem.PNum(1)).P().X(); + maxp.Y()=points->Get(elem.PNum(1)).P().Y(); + maxp.Z()=points->Get(elem.PNum(1)).P().Z(); + minp.X()=points->Get(elem.PNum(1)).P().X(); + minp.Y()=points->Get(elem.PNum(1)).P().Y(); + minp.Z()=points->Get(elem.PNum(1)).P().Z(); + + for (int i=2; i <= 3; i++) + { + maxp.X()=max2(points->Get(elem.PNum(i)).P().X(),maxp.X()); + maxp.Y()=max2(points->Get(elem.PNum(i)).P().Y(),maxp.Y()); + maxp.Z()=max2(points->Get(elem.PNum(i)).P().Z(),maxp.Z()); + minp.X()=min2(points->Get(elem.PNum(i)).P().X(),minp.X()); + minp.Y()=min2(points->Get(elem.PNum(i)).P().Y(),minp.Y()); + minp.Z()=min2(points->Get(elem.PNum(i)).P().Z(),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 Element2d& 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.); + int ix,iy,iz; + + 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; + if (ind < 1 || ind > size.i1 * size.i2 * size.i3) + { + cerr << "Illegal hash-position"; + cerr << "Position: " << ix << "," << iy << "," << iz << endl; + } + hashtable.Elem(ind)->Append(elemnum); + } + } + } +} + +void GeomSearch3d :: GetLocals(ARRAY<Element2d> & 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 Element2d & face = faces->Get(i).Face(); + + const Point3d & p1 = points->Get(face.PNum(1)).P(); + const Point3d & p2 = points->Get(face.PNum(2)).P(); + const Point3d & p3 = points->Get(face.PNum(3)).P(); + + midp = Center (p1, p2, p3); + + if (Dist2 (midp, p0) <= xh*xh) + { + 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/Netgen/libsrc/meshing/geomsearch.hpp b/Netgen/libsrc/meshing/geomsearch.hpp new file mode 100644 index 0000000000..5364c24f8d --- /dev/null +++ b/Netgen/libsrc/meshing/geomsearch.hpp @@ -0,0 +1,116 @@ +#ifndef FILE_GEOMSEARCH +#define FILE_GEOMSEARCH + +/**************************************************************************/ +/* File: geomsearch.hh */ +/* Author: Johannes Gerstmayr */ +/* Date: 19. Nov. 97 */ +/**************************************************************************/ + +class FrontPoint3; +class FrontFace; + + /// 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 Element2d& 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 Element2d& elem, INDEX elemnum); + + ///GetLocal faces in sphere with radius xh and middlepoint p + void GetLocals(ARRAY<Element2d> & 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/Netgen/libsrc/meshing/global.cpp b/Netgen/libsrc/meshing/global.cpp new file mode 100644 index 0000000000..b13367b1dc --- /dev/null +++ b/Netgen/libsrc/meshing/global.cpp @@ -0,0 +1,53 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + ostream * testout; + + ostream * mycout; + ostream * myerr; + + + // Flags globflags; // not used anymoure + Flags parameters; + + + int silentflag = 0; + int testmode = 0; + + MeshingParameters mparam; + 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/Netgen/libsrc/meshing/global.hpp b/Netgen/libsrc/meshing/global.hpp new file mode 100644 index 0000000000..843231d0c5 --- /dev/null +++ b/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 +*/ + +/// +extern double GetTime (); +extern void ResetTime (); + +/// +extern int testmode; + +// extern ostream * testout; +// extern AutoPtr<ostream> testout; + +/// calling parameters +extern Flags parameters; + +extern 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; + char * task; + bool demorunning; + multithreadt(); +}; + +extern volatile multithreadt multithread; + +extern string ngdir; +extern DebugParameters debugparam; +extern bool verbose; + +#endif diff --git a/Netgen/libsrc/meshing/hprefinement.cpp b/Netgen/libsrc/meshing/hprefinement.cpp new file mode 100644 index 0000000000..be3bbf20b2 --- /dev/null +++ b/Netgen/libsrc/meshing/hprefinement.cpp @@ -0,0 +1,3703 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ +enum HPREF_ELEMENT_TYPE { + HP_NONE=0, + HP_TRIG = 10, + HP_TRIG_SINGCORNER, + HP_TRIG_SINGCORNER12, + HP_TRIG_SINGCORNER123, + HP_TRIG_SINGEDGE = 20, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGEDGECORNER12, + 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_SINGEDGES, + + HP_TET = 100, + HP_TET_0E_1V, + HP_TET_0E_2V, + HP_TET_0E_3V, + HP_TET_0E_4V, + HP_TET_1E_0V = 200, + HP_TET_1E_1VA, // V on edge + HP_TET_1E_1VB, // V not on edge + HP_TET_1E_2VA, // both on edge + HP_TET_1E_2VB, + HP_TET_1E_2VC, + HP_TET_1E_2VD, // non on edge + HP_TET_1E_3VA, // 2 on edge + HP_TET_1E_3VB, // 1 on edge + HP_TET_1E_4V, + + // 2 connected edges, additonally marked Vs + HP_TET_2EA_0V = 220, + HP_TET_2EA_1VA, + HP_TET_2EA_1VB, + HP_TET_2EA_1VC, + HP_TET_2EA_2VA, + HP_TET_2EA_2VB, + HP_TET_2EA_2VC, + HP_TET_2EA_3V, + + // 2 opposite edges + HP_TET_2EB_0V = 230, + HP_TET_2EB_1V, + HP_TET_2EB_2VA, + HP_TET_2EB_2VB, + HP_TET_2EB_2VC, + HP_TET_2EB_3V, + HP_TET_2EB_4V, + + HP_TET_3EA_0V = 400, // 3 edges connected + HP_TET_3EA_3V, + + HP_TET_3EB_2V = 420, // 3 edges chain + HP_TET_3EC_2V = 430, // 3 edges chain, alter + HP_PRISM = 1000, + HP_PRISM_SINGEDGE, + + HP_PYRAMID = 2000, + HP_PYRAMID_0E_1V, + HP_PYRAMID_EDGES, + + HP_HEX = 3000, + HP_HEX_0E_1V, + HP_HEX_1E_0V, + HP_HEX_3E_0V, +}; + + +struct HPRef_Struct { + HPREF_ELEMENT_TYPE geom; + int (*splitedges)[3]; + int (*splitfaces)[4]; + int (*splitelements)[5]; + HPREF_ELEMENT_TYPE * neweltypes; + int (*newels)[8]; +}; + + + +// 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 +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_SINGEDGES, + 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_SINGEDGES, + 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_SINGEDGES, + 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_SINGEDGES, + 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_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_SINGEDGES +int refquad_singedges_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 3, 7 }, + { 4, 3, 8 }, + { 0, 0, 0 } +}; +int refquad_singedges_splitfaces[][4] = +{ + { 1, 2, 4, 9 }, + { 0, 0, 0, 0 }, +}; +HPREF_ELEMENT_TYPE refquad_singedges_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_NONE, +}; +int refquad_singedges_newels[][8] = +{ + { 1, 5, 9 }, + { 6, 1, 9 }, + { 5, 2, 7, 9 }, + { 4, 6, 9, 8 }, + { 9, 7, 3, 8 }, +}; +HPRef_Struct refquad_singedges = +{ + HP_QUAD, + refquad_singedges_splitedges, + refquad_singedges_splitfaces, + 0, + refquad_singedges_newelstypes, + refquad_singedges_newels +}; + + + + + + + + + + + + + +// 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_HEX, + HP_HEX, + HP_HEX, + HP_HEX, + HP_HEX, + HP_HEX, + */ + 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 }, + /* + { 5, 17, 29, 18, 8, 20, 30, 21 }, + { 6, 19, 29, 17, 11, 24, 31, 23 }, + { 7, 18, 29, 19, 14, 26, 32, 27 }, + { 9, 20, 30, 22, 12, 23, 31, 25 }, + { 10, 22, 30, 21, 15, 28, 32, 26 }, + { 13, 24, 31, 25, 16, 27, 32, 28 }, + */ + { 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_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_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_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_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_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_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_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 +}; + + + + + + + + + + + + + + +// HP_PRISM +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 +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_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, 6 } +}; +HPRef_Struct refpyramid = +{ + HP_PYRAMID, + refpyramid_splitedges, + 0, 0, + refpyramid_newelstypes, + refpyramid_newels +}; + + + +// 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 +}; + + + +// 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 +}; + + + + + + + +// HP_HEX +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_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 +}; + + + + + + +// 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 +}; + + + + +// 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, + 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 +}; + + + + + + + + +HPRef_Struct * Get_HPRef_Struct (HPREF_ELEMENT_TYPE type) +{ + HPRef_Struct * hps = NULL; + switch (type) + { + 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_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_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_SINGEDGES: + hps = &refquad_singedges; 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_2EA_0V: + hps = &reftet_2ea_0v; break; + case HP_TET_2EA_1VB: + hps = &reftet_2ea_1vb; break; + case HP_TET_2EA_3V: + hps = &reftet_2ea_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_3V: + hps = &reftet_3ea_3v; break; + + case HP_TET_3EB_2V: + hps = &reftet_3eb_2v; break; + case HP_TET_3EC_2V: + hps = &reftet_3ec_2v; break; + + case HP_PRISM: + hps = &refprism; break; + case HP_PRISM_SINGEDGE: + hps = &refprism_singedge; 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_HEX: + hps = &refhex; break; + case HP_HEX_0E_1V: + hps = &refhex_0e_1v; break; + case HP_HEX_1E_0V: + hps = &refhex_1e_0v; break; + case HP_HEX_3E_0V: + hps = &refhex_3e_0v; break; + } + + return hps; +} + + + +class HPRefElement +{ +public: + HPREF_ELEMENT_TYPE type; + int pnums[8]; + int index; + int level; +}; + +static ARRAY<HPRefElement> elements; + +void PrepareElements (Mesh & mesh) +{ + cout << "Transform mesh to hp-elements" << endl; + + int i, j, k, pi3, pi4; + INDEX_2_HASHTABLE<int> edges(mesh.GetNSeg()+1); + BitArray edgepoint(mesh.GetNP()); + edgepoint.Clear(); + BitArray cornerpoint(mesh.GetNP()); + cornerpoint.Clear(); + + // check, if point has as least 3 different surfs: + ARRAY<INDEX_3> surfonpoint(mesh.GetNP()); + + if (mesh.GetDimension() == 3) + { + for (i = 1; i <= mesh.GetNP(); i++) + surfonpoint.Elem(i) = INDEX_3(0,0,0); + for (i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & el = mesh.SurfaceElement(i); + int ind = el.GetIndex(); + for (j = 0; j < el.GetNP(); j++) + { + int pi = el[j]; + INDEX_3 & i3 = surfonpoint.Elem(pi); + if (ind != i3.I1() && + ind != i3.I2() && + ind != i3.I3()) + { + i3.I1() = i3.I2(); + i3.I2() = i3.I3(); + i3.I3() = ind; + } + } + } + for (i = 1; i <= mesh.GetNP(); i++) + if (surfonpoint.Get(i).I1()) + cornerpoint.Set(i); + + // cornerpoint.Clear(); + // cornerpoint.Set(1); + + for (i = 1; i <= mesh.GetNSeg(); i++) + { + INDEX_2 i2 (mesh.LineSegment(i).p1, + mesh.LineSegment(i).p2); + i2.Sort(); + // if (i2.I1() == 11 && i2.I2() == 12) + { + edges.Set (i2, 1); + edgepoint.Set (i2.I1()); + edgepoint.Set (i2.I2()); + } + } + } + else + { + for (i = 1; i <= mesh.GetNP(); i++) + surfonpoint.Elem(i) = INDEX_3(0,0,0); + + for (i = 1; i <= mesh.GetNSeg(); i++) + { + const Segment & seg = mesh.LineSegment(i); + int ind = seg.edgenr; + if (ind <= 12) continue; + + INDEX_2 i2 (mesh.LineSegment(i).p1, + mesh.LineSegment(i).p2); + i2.Sort(); + edges.Set (i2, 1); + edgepoint.Set(i2.I1()); + edgepoint.Set(i2.I2()); + + // (*testout) << "seg = " << ind << ", " << seg.p1 << "-" << seg.p2 << endl; + for (j = 0; j < 2; j++) + { + int pi = (j == 0) ? seg.p1 : seg.p2; + // if (pi > 20) + { + INDEX_3 & i3 = surfonpoint.Elem(pi); + if (ind != i3.I1() && + ind != i3.I2()) + { + i3.I1() = i3.I2(); + i3.I2() = ind; + } + } + } + } + for (i = 1; i <= mesh.GetNP(); i++) + if (surfonpoint.Get(i).I1()) + { + cornerpoint.Set(i); + } + } + + int cnt_undef = 0, cnt_nonimplement = 0; + ARRAY<int> misses(10000); + misses = 0; + + for (i = 1; i <= mesh.GetNE(); i++) + { + Element & el = mesh.VolumeElement(i); + + HPREF_ELEMENT_TYPE type = HP_NONE; + int pnums[8] = { 0 }; + + + switch (el.GetType()) + { + case TET: + { + int ep1, ep2, ep3, ep4, cp1, cp2, cp3, cp4; + int isedge1, isedge2, isedge3, isedge4, isedge5, isedge6; + + for (j = 1; j <= 4; j++) + for (k = 1; k <= 4; k++) + { + if (j == k) continue; + if (type) break; + + int pi3 = 1; + while (pi3 == j || pi3 == k) pi3++; + pi4 = 10 - 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.PNum (j)); + ep2 = edgepoint.Test (el.PNum (k)); + ep3 = edgepoint.Test (el.PNum (pi3)); + ep4 = edgepoint.Test (el.PNum (pi4)); + + cp1 = cornerpoint.Test (el.PNum (j)); + cp2 = cornerpoint.Test (el.PNum (k)); + cp3 = cornerpoint.Test (el.PNum (pi3)); + cp4 = cornerpoint.Test (el.PNum (pi4)); + + INDEX_2 i2; + i2 = INDEX_2(el.PNum (j), el.PNum (k)); + i2.Sort(); + isedge1 = edges.Used (i2); + + i2 = INDEX_2(el.PNum (j), el.PNum (pi3)); + i2.Sort(); + isedge2 = edges.Used (i2); + + i2 = INDEX_2(el.PNum (j), el.PNum (pi4)); + i2.Sort(); + isedge3 = edges.Used (i2); + + i2 = INDEX_2(el.PNum (k), el.PNum (pi3)); + i2.Sort(); + isedge4 = edges.Used (i2); + + i2 = INDEX_2(el.PNum (k), el.PNum (pi4)); + i2.Sort(); + isedge5 = edges.Used (i2); + + i2 = INDEX_2(el.PNum (pi3), el.PNum (pi4)); + i2.Sort(); + isedge6 = edges.Used (i2); + + 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; + } + } + + case 3: + { + if (isedge1 && isedge2 && isedge3) + { + if (!cp2 && !cp3 && !cp4) + type = HP_TET_3EA_0V; + if (cp2 && cp3 && ep4) + type = HP_TET_3EA_3V; + } + if (isedge1 && isedge3 && isedge4) + { + if (cp3 && ep4) + type = HP_TET_3EB_2V; + } + if (isedge1 && isedge2 && isedge5) + { + if (cp3 && ep4) + type = HP_TET_3EC_2V; + } + } + } + + if (type != HP_NONE) + { + pnums[0] = el.PNumMod (j); + pnums[1] = el.PNumMod (k); + pnums[2] = el.PNumMod (pi3); + pnums[3] = el.PNumMod (pi4); + break; + } + } + + + 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; + } + // cout << "hpref - element = " << type << endl; + + + + break; + } + case PRISM: + { + int pi1, pi2, pi3, pi4, pi5, pi6; + int ep1, ep2, ep3, ep4, ep5, ep6, cp1, cp2, cp3, cp4, cp5, cp6; + + int ishedge1, ishedge2, ishedge3, ishedge4, ishedge5, ishedge6; + int isvedge1, isvedge2, isvedge3; + + for (j = 1; j <= 3; j++) + { + if (type) break; + + pi1 = j; + pi2 = pi1%3 + 1; + pi3 = pi2%3 + 1; + pi4 = pi1+3; + pi5 = pi2+3; + pi6 = pi3+3; + + ep1 = edgepoint.Test (el.PNum (pi1)); + ep2 = edgepoint.Test (el.PNum (pi2)); + ep3 = edgepoint.Test (el.PNum (pi3)); + ep4 = edgepoint.Test (el.PNum (pi4)); + ep5 = edgepoint.Test (el.PNum (pi5)); + ep6 = edgepoint.Test (el.PNum (pi6)); + + cp1 = cornerpoint.Test (el.PNum (pi1)); + cp2 = cornerpoint.Test (el.PNum (pi2)); + cp3 = cornerpoint.Test (el.PNum (pi3)); + cp4 = cornerpoint.Test (el.PNum (pi4)); + cp5 = cornerpoint.Test (el.PNum (pi5)); + cp6 = cornerpoint.Test (el.PNum (pi6)); + + INDEX_2 i2; + i2 = INDEX_2(el.PNum (pi1), el.PNum (pi4)); + i2.Sort(); + isvedge1 = edges.Used (i2); + + + if (isvedge1 + isvedge2 + isvedge3 == 0) + { + type = HP_PRISM; + } + else if (isvedge1) + { + type = HP_PRISM_SINGEDGE; + } + + + if (type != HP_NONE) + { + pnums[0] = el.PNum (pi1); + pnums[1] = el.PNum (pi2); + pnums[2] = el.PNum (pi3); + pnums[3] = el.PNum (pi4); + pnums[4] = el.PNum (pi5); + pnums[5] = el.PNum (pi6); + break; + } + } + break; + } + default: + { + cerr << "hp-refinement not defined for element" << endl; + } + } + + if (!Get_HPRef_Struct (type)) + { + (*testout) << "case " << type << " not implemented " << endl; + cnt_nonimplement++; + misses[type]++; + } + + HPRefElement hpel; + hpel.type = type; + for (j = 0; j < 8; j++) + hpel.pnums[j] = pnums[j]; + hpel.index = el.GetIndex(); + hpel.level = 1; + elements.Append (hpel); + } + + cout << "undefined elements: " << cnt_undef << endl; + cout << "non-implemented: " << cnt_nonimplement << endl; + + for (i = 0; i < misses.Size(); i++) + if (misses[i]) + cout << "missing case " << i << " occured " << misses[i] << " times" << endl; + + for (i = 1; i <= mesh.GetNSE(); i++) + { + Element2d & el = mesh.SurfaceElement(i); + + HPREF_ELEMENT_TYPE type = HP_NONE; + int pnums[8] = { 0 }; + + switch (el.GetType()) + { + case TRIG: + { + for (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)); + + int cp1 = cornerpoint.Test (el.PNumMod (j)); + int cp2 = cornerpoint.Test (el.PNumMod (j+1)); + int cp3 = cornerpoint.Test (el.PNumMod (j+2)); + + INDEX_2 i2; + i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); + i2.Sort(); + int isedge1 = edges.Used (i2); + i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); + i2.Sort(); + int isedge2 = edges.Used (i2); + i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); + i2.Sort(); + int isedge3 = edges.Used (i2); + + 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) + 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; + } + } + break; + } + case QUAD: + { + for (j = 1; j <= 4; j++) + { + int ep1 = edgepoint.Test (el.PNumMod (j)); + int ep2 = edgepoint.Test (el.PNumMod (j+1)); + int ep3 = edgepoint.Test (el.PNumMod (j+2)); + int ep4 = edgepoint.Test (el.PNumMod (j+3)); + + int cp1 = cornerpoint.Test (el.PNumMod (j)); + int cp2 = cornerpoint.Test (el.PNumMod (j+1)); + int cp3 = cornerpoint.Test (el.PNumMod (j+2)); + int cp4 = cornerpoint.Test (el.PNumMod (j+3)); + + INDEX_2 i2; + i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); + i2.Sort(); + int isedge1 = edges.Used (i2); + i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); + i2.Sort(); + int isedge2 = edges.Used (i2); + i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); + i2.Sort(); + int isedge3 = edges.Used (i2); + i2 = INDEX_2(el.PNumMod (j+3), el.PNumMod (j+4)); + i2.Sort(); + int isedge4 = edges.Used (i2); + + + if (isedge1 + isedge2 + isedge3 + isedge4 == 0) + { + type = HP_QUAD; + } + else if (isedge1) + { + type = HP_QUAD_SINGEDGE; + } + + if (type != HP_NONE) + { + pnums[0] = el.PNumMod (j); + pnums[1] = el.PNumMod (j+1); + pnums[2] = el.PNumMod (j+2); + pnums[3] = el.PNumMod (j+3); + break; + } + } + break; + } + } + + HPRefElement hpel; + hpel.type = type; + for (j = 0; j < 8; j++) + hpel.pnums[j] = pnums[j]; + hpel.index = el.GetIndex(); + hpel.level = 1; + + elements.Append (hpel); + } +} + + + +void DoRefinement (Mesh & mesh) +{ + int i, j, k; + + INDEX_2_HASHTABLE<int> newpts(elements.Size()+1); + INDEX_3_HASHTABLE<int> newfacepts(elements.Size()+1); + + // prepare new points + + (*testout) << "find new points" << endl; + int oldelsize = elements.Size(); + for (i = 1; i <= oldelsize; i++) + { + (*testout) << "el " << i << endl; + + HPRefElement & el = elements.Elem(i); + HPRef_Struct * hprs = Get_HPRef_Struct (el.type); + + (*testout) << "type = " << el.type << endl; + + + if (!hprs) + { + // cout << "Refinementstruct not defined for element " << el.type << endl; + continue; + } + + 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)) + { + Point3d np = Center (mesh.Point (i2.I1()), + mesh.Point (i2.I2())); + np = Center (mesh.Point (i2.I1()),np); + np = Center (mesh.Point (i2.I1()),np); + 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)) + { + Point3d np = Center (mesh.Point (i3.I2()), + mesh.Point (i3.I3())); + np = Center (mesh.Point (i3.I1()),np); + np = Center (mesh.Point (i3.I1()),np); + int npi = mesh.AddPoint (np); + newfacepts.Set (i3, npi); + } + j++; + } + } + + + + (*testout) << "generate elements" << endl; + + for (i = 1; i <= oldelsize; i++) + { + (*testout) << "el " << i << endl; + + HPRefElement & el = elements.Elem(i); + HPRef_Struct * hprs = Get_HPRef_Struct (el.type); + int newlevel = el.level + 1; + + if (el.type == HP_TRIG || + el.type == HP_QUAD || + el.type == HP_TET || + el.type == HP_PRISM || + el.type == HP_HEX) + newlevel = el.level; + + (*testout) << "type = " << el.type << endl; + + if (!hprs) + { + continue; + } + + int newpnums[33]; + for (j = 0; j < 8; j++) + newpnums[j] = el.pnums[j]; + + 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; + 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()); + int npi = newfacepts.Get(i3); + newpnums[hprs->splitfaces[j][3]-1] = npi; + j++; + } + + + j = 0; + if (hprs->splitelements) + while (hprs->splitelements[j][0]) + { + int pi1 = el.pnums[hprs->splitelements[j][0]-1]; + Point3d np = + Center (Center (mesh.Point (pi1), + mesh.Point (el.pnums[hprs->splitelements[j][1]-1])), + Center (mesh.Point (el.pnums[hprs->splitelements[j][2]-1]), + mesh.Point (el.pnums[hprs->splitelements[j][3]-1]))); + + np = Center (mesh.Point (pi1),np); + int npi = mesh.AddPoint (np); + newpnums[hprs->splitelements[j][4]-1] = npi; + j++; + } + (*testout) << "type = " << el.type << endl; + (*testout) << "newpnums = "; + for (k = 0; k < 10; k++) + (*testout) << newpnums[k] << " "; + (*testout) << endl; + + j = 0; + while (hprs->neweltypes[j]) + { + HPRefElement newel; + newel.type = hprs->neweltypes[j]; + for (k = 0; k < 8; k++) + newel.pnums[k] = newpnums[hprs->newels[j][k]-1]; + + if (newel.pnums[1] == newel.pnums[3]) + { + cout << "same node numbers !!!! " << endl; + (*testout) << "same node numbers !!!! " << endl; + } + (*testout) << "new el: "; + for (k = 0; k < 8; k++) + (*testout) << newel.pnums[k] << " "; + (*testout) << endl; + + newel.index = elements.Elem(i).index; + newel.level = newlevel; + + if (j == 0) + elements.Elem(i) = newel; + else + elements.Append (newel); + j++; + } + (*testout) << "el complete" << endl; + } + + cout << "refinement done" << endl; +} + + + +void DoRefineDummies (Mesh & mesh) +{ + cout << "refine dummies" << endl; + int i, j, k; + + int oldelsize = elements.Size(); + + for (i = 1; i <= oldelsize; i++) + { + HPRefElement & el = elements.Elem(i); + HPRef_Struct * hprs = Get_HPRef_Struct (el.type); + + int newlevel = el.level; + + 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_0V && + el.type != HP_HEX_3E_0V + ) continue; + + if (!hprs) continue; + + int newpnums[33]; + for (j = 0; j < 8; j++) + newpnums[j] = el.pnums[j]; + + j = 0; + while (hprs->neweltypes[j]) + { + HPRefElement newel; + newel.type = hprs->neweltypes[j]; + for (k = 0; k < 8; k++) + newel.pnums[k] = newpnums[hprs->newels[j][k]-1]; + newel.index = el.index; + + newel.level = newlevel; + + if (j == 0) + elements.Elem(i) = newel; + else + elements.Append (newel); + j++; + } + } + cout << "refineme dummies done" << endl; +} + + + + + + + +void CalcStatistics () +{ + int i, p; + int ntrig = 0, nquad = 0; + int nhex = 0, nprism = 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 (el.type) + { + case HP_TRIG: + case HP_TRIG_SINGCORNER: + case HP_TRIG_SINGEDGE: + case HP_TRIG_SINGEDGECORNER1: + case HP_TRIG_SINGEDGECORNER2: + { + ntrig ++; + break; + } + case HP_QUAD: + case HP_QUAD_SINGEDGE: + { + nquad++; + break; + } + case HP_TET: + case HP_TET_0E_1V: + case HP_TET_1E_0V: + case HP_TET_1E_1VA: + { + ntet++; + break; + } + + case HP_PRISM: + case HP_PRISM_SINGEDGE: + { + nprism++; + break; + } + + case HP_HEX: + { + nhex++; + break; + } + } + } + + cout << "level = " << maxlevel << endl; + cout << "ntrig = " << ntrig << ", nquad = " << nquad << endl; + cout << "ntet = " << ntet << ", nprism = " << nprism << ", nhex = " << nhex << endl; + + return; + + double memcost = 0, cpucost = 0; + for (p = 1; p <= 20; p++) + { + memcost = (ntet + nprism + nhex) * pow (p, 6.0); + cpucost = (ntet + nprism + nhex) * pow (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 (p1, 6.0) + << " (p1-3)^6 = " << pow ( max2(p1-3, 0), 6.0) + << " p1^3 = " << pow ( p1, 3.0) + << " (p1-3)^3 = " << pow ( p1-3, 3.0) + << " [p1^3-(p1-3)^3]^2 = " << sqr (pow (p1,3.0) - pow ( p1-3, 3.0)) + << endl; + + p1 /= 2 +1; + memcosttet += pow (p1, 6.0); + memcostsctet += pow (p1, 6.0) - pow ( max2(p1-3, 1), 6.0); + cpucosttet += pow (p1, 9.0); + break; + } + case HP_PRISM: + case HP_PRISM_SINGEDGE: + { + int p1 = maxlevel - el.level + 1; + p1 /= 2 +1; + memcostprism += pow (p1, 6.0); + memcostscprism += pow (p1, 6.0) - pow ( max2(p1-3, 1), 6.0); + cpucostprism += pow (p1, 9.0); + break; + } + case HP_HEX: + { + int p1 = maxlevel - el.level + 1; + int p2 = maxlevel; + p1 /= 2 +1; + p2 /= 2 +1; + memcosthex += pow (p1, 4.0) * pow (p2, 2.0); + memcostschex += pow (p1, 6.0) - pow ( max2(p1-2, 0), 6.0); + cpucosthex += pow (p1, 6.0) * pow (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; +} + +void HPRefinement (Mesh & mesh, int levels) +{ + int i, j; + cout << "HP Refinement called, levels = " << levels; + + PrepareElements (mesh); + + for (j = 1; j <= levels; j++) + { + DoRefinement (mesh); + DoRefineDummies (mesh); + CalcStatistics (); + } + + mesh.ClearSurfaceElements(); + mesh.ClearVolumeElements(); + + for (i = 1; i <= elements.Size(); i++) + { + HPRefElement & hpel = elements.Elem(i); + if (Get_HPRef_Struct (hpel.type)) + switch (Get_HPRef_Struct (hpel.type) -> geom) + { + case HP_TRIG: + { + Element2d el(3); + el.PNum(1) = hpel.pnums[0]; + el.PNum(2) = hpel.pnums[1]; + el.PNum(3) = hpel.pnums[2]; + el.SetIndex (hpel.index); + mesh.AddSurfaceElement (el); + break; + } + case HP_QUAD: + { + Element2d el(4); + el.PNum(1) = hpel.pnums[0]; + el.PNum(2) = hpel.pnums[1]; + el.PNum(3) = hpel.pnums[2]; + el.PNum(4) = hpel.pnums[3]; + el.SetIndex (hpel.index); + mesh.AddSurfaceElement (el); + break; + } + case HP_TET: + { + Element el(4); + el.PNum(1) = hpel.pnums[0]; + el.PNum(2) = hpel.pnums[1]; + el.PNum(3) = hpel.pnums[2]; + el.PNum(4) = hpel.pnums[3]; + el.SetIndex (hpel.index); + mesh.AddVolumeElement (el); + break; + } + case HP_PRISM: + { + Element el(6); + el.PNum(1) = hpel.pnums[0]; + el.PNum(2) = hpel.pnums[1]; + el.PNum(3) = hpel.pnums[2]; + el.PNum(4) = hpel.pnums[3]; + el.PNum(5) = hpel.pnums[4]; + el.PNum(6) = hpel.pnums[5]; + el.SetIndex (hpel.index); + mesh.AddVolumeElement (el); + break; + } + + case HP_PYRAMID: + { + Element el(5); + el.PNum(1) = hpel.pnums[0]; + el.PNum(2) = hpel.pnums[1]; + el.PNum(3) = hpel.pnums[2]; + el.PNum(4) = hpel.pnums[3]; + el.PNum(5) = hpel.pnums[4]; + el.SetIndex (hpel.index); + mesh.AddVolumeElement (el); + break; + } + case HP_HEX: + { + Element el(8); + el.PNum(1) = hpel.pnums[0]; + el.PNum(2) = hpel.pnums[1]; + el.PNum(3) = hpel.pnums[2]; + el.PNum(4) = hpel.pnums[3]; + el.PNum(5) = hpel.pnums[4]; + el.PNum(6) = hpel.pnums[5]; + el.PNum(7) = hpel.pnums[6]; + el.PNum(8) = hpel.pnums[7]; + + (*testout) << "hex: " << endl; + for (int ii = 1; ii <= 8; ii++) + (*testout) << hpel.pnums[ii-1] << " "; + (*testout) << endl; + + el.SetIndex (hpel.index); + mesh.AddVolumeElement (el); + break; + } + + default: + PrintSysError ("hpref, backconversion failed for element ", + int(Get_HPRef_Struct (hpel.type) -> geom)); + } + } + + mesh.UpdateTopology(); +} + + +} diff --git a/Netgen/libsrc/meshing/hprefinement.hpp b/Netgen/libsrc/meshing/hprefinement.hpp new file mode 100644 index 0000000000..ca21a886d6 --- /dev/null +++ b/Netgen/libsrc/meshing/hprefinement.hpp @@ -0,0 +1,22 @@ +#ifndef FILE_HPREFINEMENT +#define FILE_HPREFINEMENT + +/**************************************************************************/ +/* File: hprefinement.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 27. Oct. 2000 */ +/**************************************************************************/ + +/* + HP Refinement +*/ + + +extern void HPRefinement (Mesh & mesh, int levels); + + +#endif + + + + diff --git a/Netgen/libsrc/meshing/improve2.cpp b/Netgen/libsrc/meshing/improve2.cpp new file mode 100644 index 0000000000..e70944d69b --- /dev/null +++ b/Netgen/libsrc/meshing/improve2.cpp @@ -0,0 +1,766 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#include <opti.hpp> + +//removed for gmsh +//#include <visual.hpp> + + +namespace netgen +{ + +class Neighbour +{ + int nr[3]; + int orient[3]; + +public: + Neighbour () { nr[0] = nr[1] = nr[2] = -1; orient[0] = orient[1] = orient[2] = 0; } + + void SetNr (int side, int anr) { nr[side-1] = anr; } + int GetNr (int side) { return nr[side-1]; } + + void SetOrientation (int side, int aorient) { orient[side-1] = aorient; } + int GetOrientation (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; + return; + } + + int i, i2, j, k, j2; + bool should; + PointIndex pi; + + ARRAY<SurfaceElementIndex> seia; + mesh.GetSurfaceElementsOfFace (faceindex, seia); + + for (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()); + + SurfaceElementIndex t1, t2; + int o1, o2; + + PointIndex pi1, pi2, pi3, pi4; + PointGeomInfo gi1, gi2, gi3, gi4; + + + int nswaps = 0; + int e, done; + double d; + Vec3d nv1, nv2; + double horder; + double loch; + static const double minangle[] = { 0, 1.481, 2.565, 3.627, 4.683, 5.736, 7, 9 }; + + pangle = 0; + + for (i = 0; i < seia.Size(); i++) + { + const Element2d & sel = mesh[seia[i]]; + for (j = 0; j < 3; j++) + { + POINTTYPE typ = mesh.PointType (sel[j]); + 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 (pi = PointIndex::BASE; + pi < mesh.GetNP()+PointIndex::BASE; pi++) + { + if (mesh.PointType(pi) == INNERPOINT || mesh.PointType(pi) == SURFACEPOINT) + pdef[pi] = -6; + else + for (j = 0; j < 8; j++) + if (pangle[pi] >= minangle[j]) + pdef[pi] = -1-j; + } + + for (i = 0; i < seia.Size(); i++) + { + const Element2d & sel = mesh[seia[i]]; + for (j = 0; j < 3; j++) + pdef[sel[j]]++; + } + + for (i = 0; i < seia.Size(); i++) + { + const Element2d & sel = mesh[seia[i]]; + for (j = 0; j < 3; j++) + { + neighbors[seia[i]].SetNr (j+1, -1); + neighbors[seia[i]].SetOrientation (j+1, 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 (i = 0; i < seia.Size(); i++) + { + const Element2d & sel = mesh[seia[i]]; + + for (j = 1; j <= 3; j++) + { + pi1 = sel.PNumMod(j+1); + pi2 = sel.PNumMod(j+2); + + 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(); + + i2 = other.Get(ii2).tnr; + 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 (i = 0; i < seia.Size(); i++) + swapped[seia[i]] = 0; + + + int t = 4; + done = 0; + while (!done && t >= 2) + { + for (i = 0; i < seia.Size(); i++) + { + t1 = seia[i]; + + if (mesh[t1].IsDeleted()) + continue; + + if (mesh[t1].GetIndex() != faceindex) + continue; + + if (multithread.terminate) + throw NgException ("Meshing stopped"); + + for (o1 = 1; o1 <= 3; o1++) + { + t2 = neighbors[t1].GetNr (o1); + o2 = neighbors[t1].GetOrientation (o1); + + if (t2 == -1) continue; + if (swapped[t1] || swapped[t2]) continue; + + + pi1 = mesh[t1].PNumMod(o1+1); + pi2 = mesh[t1].PNumMod(o1+2); + pi3 = mesh[t1].PNumMod(o1); + pi4 = mesh[t2].PNumMod(o2); + + gi1 = mesh[t1].GeomInfoPiMod(o1+1); + gi2 = mesh[t1].GeomInfoPiMod(o1+2); + gi3 = mesh[t1].GeomInfoPiMod(o1); + gi4 = mesh[t2].GeomInfoPiMod(o2); + + // normal of old + nv1 = Cross (mesh.Point(pi3)-mesh.Point(pi4), + mesh.Point(pi1)-mesh.Point(pi4)); + nv2 = Cross (mesh.Point(pi4)-mesh.Point(pi3), + mesh.Point(pi2)-mesh.Point(pi3)); + + + // normals of swapped + Vec3d nv3, nv4; + nv3 = Cross (mesh.Point(pi1)-mesh.Point(pi4), + mesh.Point(pi2)-mesh.Point(pi4)); + nv4 = Cross (mesh.Point(pi2)-mesh.Point(pi3), + mesh.Point(pi1)-mesh.Point(pi3)); + + + nv1.Normalize(); + nv2.Normalize(); + + Vec3d 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 + bool allowswap = + (nv1 * nvp3 > critval) && + (nv1 * nvp4 > critval) && + (nv2 * nvp3 > critval) && + (nv2 * nvp4 > critval) && + (nvp3 * nv3 > critval) && + (nvp4 * nv4 > critval); + + 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) + { + e = pdef[pi1] + pdef[pi2] - pdef[pi3] - pdef[pi4]; + d = + Dist2 (mesh.Point(pi1), mesh.Point(pi2)) - + Dist2 (mesh.Point(pi3), mesh.Point(pi4)); + + should = e >= t && (e > 2 || d > 0); + } + else + { + 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 (pi4, 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 ! + + nswaps ++; + + // testout << "nv1 = " << nv1 << " nv2 = " << nv2 << endl; + + 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.Elem(t1) = 1; + swapped.Elem(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; + } + + + int i, j, k, l, i2, j2; + PointIndex pi; + SurfaceElementIndex sei; + + + ARRAY<SurfaceElementIndex> seia; + mesh.GetSurfaceElementsOfFace (faceindex, seia); + + + for (i = 0; i < seia.Size(); i++) + if (mesh[seia[i]].GetNP() != 3) + return; + + + + int surfnr = 0; + if (faceindex) + surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr(); + + + int should; + PointIndex pi1, pi2; + Point3d p1, p2, pnew; + double bad1, bad2; + Vec3d nv; + + int np = mesh.GetNP(); + int nse = mesh.GetNSE(); + + TABLE<SurfaceElementIndex,PointIndex::BASE> elementsonnode(np); + ARRAY<SurfaceElementIndex> hasonepi, hasbothpi; + + for (i = 0; i < seia.Size(); i++) + { + Element2d & el = mesh[seia[i]]; + for (j = 0; j < el.GetNP(); j++) + elementsonnode.Add (el[j], seia[i]); + } + + ARRAY<int,PointIndex::BASE> fixed(np); + fixed = 0; + + SegmentIndex si; + for (si = 0; si < mesh.GetNSeg(); si++) + { + INDEX_2 i2(mesh[si].p1, mesh[si].p2); + fixed[i2.I1()] = 1; + fixed[i2.I2()] = 1; + } + + + ARRAY<Vec3d,PointIndex::BASE> normals(np); + + for (pi = PointIndex::BASE; + pi < np + PointIndex::BASE; pi++) + { + if (elementsonnode[pi].Size()) + { + Element2d & hel = mesh[elementsonnode[pi][0]]; + for (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; + } + if (k == 3) + { + cerr << "Neuer Fehler von Joachim, code 17121" << endl; + } + } + } + + + for (i = 0; i < seia.Size(); i++) + { + sei = seia[i]; + Element2d & elem = mesh[sei]; + if (elem.IsDeleted()) continue; + + for (j = 0; j < 3; j++) + { + pi1 = elem[j]; + 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 (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 (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; + } + if (k == 3) + { + cerr << "Neuer Fehler von Joachim, code 32434" << endl; + } + + + // nv = normals.Get(pi1); + + + for (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 (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 (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()); + + p1 = mesh[pi1]; + p2 = mesh[pi2]; + + pnew = p1; + mesh[pi1] = pnew; + mesh[pi2] = pnew; + + bad2 = 0; + for (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; + + Vec3d hnv = Cross (Vec3d (mesh[el[0]], + mesh[el[1]]), + Vec3d (mesh[el[0]], + mesh[el[2]])); + if (hnv * nv < 0) + bad2 += 1e10; + + for (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; + + Element2d & el1 = mesh[elementsonnode[pi1][0]]; + for (l = 0; l < el1.GetNP(); l++) + if (el1[l] == pi1) + gi = el1.GeomInfoPi (l+1); + + + // (*testout) << "Connect point " << pi2 << " to " << pi1 << "\n"; + for (k = 0; k < elementsonnode[pi2].Size(); k++) + { + Element2d & el = mesh[elementsonnode[pi2][k]]; + 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 (l = 0; l < el.GetNP(); l++) + { + if (el[l] == pi2) + { + el[l] = pi1; + el.GeomInfoPi (l+1) = gi; + } + + fixed[el[l]] = 1; + } + } + + /* + 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 (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/Netgen/libsrc/meshing/improve2.hpp b/Netgen/libsrc/meshing/improve2.hpp new file mode 100644 index 0000000000..39cd1be018 --- /dev/null +++ b/Netgen/libsrc/meshing/improve2.hpp @@ -0,0 +1,91 @@ +#ifndef FILE_IMPROVE2 +#define FILE_IMPROVE2 + + + +/// +class MeshOptimize2d +{ + int faceindex; + int improveedges; + double metricweight; + int writestatus; + +public: + /// + MeshOptimize2d (); + /// + void ImproveMesh (Mesh & mesh2d); + void ImproveMeshJacobian (Mesh & mesh2d); + + 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 Point3d & p, + const PointGeomInfo & gi); + /// + virtual void ProjectPoint (INDEX /* surfind */, Point3d & /* p */) const { }; + /// + virtual void ProjectPoint2 (INDEX /* surfind */, INDEX /* surfind2 */, Point3d & /* 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 Point3d& /*p3*/) const + { gi.trignum = 1; return 1;}; + + virtual int CalcPointGeomInfo(int surfind, PointGeomInfo& gi, const Point3d& p3) const + { return CalcPointGeomInfo (gi, p3); } + + /// + virtual void GetNormalVector(INDEX surfind, const Point3d & p, PointGeomInfo & gi, Vec3d & n) const; + virtual void GetNormalVector(INDEX surfind, const Point3d & p, Vec3d & 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/Netgen/libsrc/meshing/improve2gen.cpp b/Netgen/libsrc/meshing/improve2gen.cpp new file mode 100644 index 0000000000..40291575f5 --- /dev/null +++ b/Netgen/libsrc/meshing/improve2gen.cpp @@ -0,0 +1,465 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#include <opti.hpp> + +namespace netgen +{ + + class ImprovementRule + { + public: + ARRAY<Element2d> oldels; + ARRAY<Element2d> newels; + 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; + + 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->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->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->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->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->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->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->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->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->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->onp = 5; + r1->bonus = 0; + rules.Append (r1); + + + + + ARRAY<int> mapped(rules.Size()); + ARRAY<int> used(rules.Size()); + used = 0; + mapped = 0; + + + + for (ri = 0; ri < rules.Size(); ri++) + { + ImprovementRule & rule = *rules[ri]; + rule.incelsonnode.SetSize (rule.onp); + rule.reused.SetSize (rule.onp); + + for (j = 1; j <= rule.onp; j++) + { + rule.incelsonnode.Elem(j) = 0; + rule.reused.Elem(j) = 0; + } + + for (j = 1; j <= rule.oldels.Size(); j++) + { + const Element2d & el = rule.oldels.Elem(j); + for (k = 1; k <= el.GetNP(); k++) + rule.incelsonnode.Elem(el.PNum(k))--; + } + + for (j = 1; j <= rule.newels.Size(); j++) + { + const Element2d & el = rule.newels.Elem(j); + for (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<int> nbels(ne); + + nelonnode = -4; + + for (sei = 0; sei < ne; sei++) + { + const Element2d & el = mesh[sei]; + if (el.GetIndex() == faceindex) + { + for (j = 0; j < el.GetNP(); j++) + elonnode.Add (el[j], sei); + } + for (j = 0; j < el.GetNP(); j++) + nelonnode[el[j]]++; + } + + for (sei = 0; sei < ne; sei++) + { + const Element2d & el = mesh[sei]; + if (el.GetIndex() == faceindex) + { + for (j = 0; j < el.GetNP(); j++) + { + for (k = 0; k < elonnode[el[j]].Size(); k++) + { + int nbel = elonnode[el[j]] [k]; + int used = 0; + for (l = 0; l < nbels[sei].Size(); l++) + if (nbels[sei][l] == nbel) + used = 1; + if (!used) + nbels.Add (sei, nbel); + } + } + } + } + + + for (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); + + + // loop over elements and rotations: + /* + int nt = int (pow (ne, elmap.Size())); + for (i = 1; i <= nt; i++) + { + int hi = i-1; + for (j = 1; j <= elmap.Size(); j++) + { + elmap.Elem (j) = hi % ne + 1; + hi /= ne; + } + */ + + for (sei = 0; sei < ne; sei++) + { + if (multithread.terminate) + break; + + elmap[0] = sei; + + int nnb = nbels[sei].Size(); + int nt = int (pow (double(nnb), double(elmap.Size()-1))); + + for (int i = 1; i <= nt; i++) + { + int hi = i-1; + for (j = 1; j < elmap.Size(); j++) + { + elmap[j] = nbels[sei][hi % nnb]; + hi /= nnb; + } + + ok = 1; + for (j = 0; j < elmap.Size(); j++) + { + const Element2d & el = mesh.SurfaceElement(elmap[j]); + const Element2d & rel = rule.oldels[j]; + + if (el.GetNP() != rel.GetNP()) { ok = 0; break; } + if (el.IsDeleted()) { ok = 0; break; } + } + + if (!ok) continue; + + + int nr = int (pow (4.0, elmap.Size())); + for (int i2 = 1; i2 <= nr; i2++) + { + int hi2 = i2-1; + for (j = 1; j <= elmap.Size(); j++) + { + elrot.Elem (j) = hi2 % 4 + 1; + hi2 /= 4; + } + + + // check applicable + + ok = 1; + + // set mapped points + for (j = 1; j <= elmap.Size(); j++) + { + const Element2d & el = mesh.SurfaceElement(elmap.Get(j)); + const Element2d & rel = rule.oldels.Get(j); + + /* + if (el.GetNP() != rel.GetNP()) + { + ok = 0; + break; + } + */ + + for (k = 1; k <= el.GetNP(); k++) + { + /* + if (el.PNum(k) < PointIndex::BASE) + { + ok = 0; + break; + } + */ + pmap.Elem(rel.PNum(k)) = + el.PNumMod(k+elrot.Get(j)); + pgi.Elem(rel.PNum(k)) = + el.GeomInfoPiMod(k+elrot.Get(j)); + } + } + if (!ok) continue; + + /* + (*testout) << "candidates found: " << endl; + for (j = 1; j <= elmap.Size(); j++) + { + const Element2d & el = mesh.SurfaceElement(elmap.Get(j)); + (*testout) << "el " << elmap.Get(j) + << ", rot = " << elrot.Get(j) << " " + << el << endl; + } + */ + + + // check consistently mapped points: + for (j = 1; j <= elmap.Size(); j++) + { + const Element2d & el = mesh.SurfaceElement(elmap.Get(j)); + const Element2d & rel = rule.oldels.Get(j); + + for (k = 1; k <= el.GetNP(); k++) + { + if (pmap.Elem(rel.PNum(k)) != el.PNumMod(k+elrot.Get(j))) + ok = 0; + } + } + + if (!ok) continue; + + + mapped[ri]++; + + /* + (*testout) << "application found: " << endl; + for (j = 1; j <= elmap.Size(); j++) + { + const Element2d & el = mesh.SurfaceElement(elmap.Get(j)); + (*testout) << "el " << elmap.Get(j) + << ", rot = " << elrot.Get(j) << " " + << el << endl; + } + (*testout) << "points:"; + for (j = 1; j <= pmap.Size(); j++) + (*testout) << " " << pmap.Get(j); + (*testout) << endl; + */ + + olddef = 0; + for (j = 1; j <= pmap.Size(); j++) + olddef += sqr (nelonnode[pmap.Get(j)]); + olddef += rule.bonus; + + newdef = 0; + for (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; + Vec3d n; + + SelectSurfaceOfPoint (mesh.Point(pmap.Get(1)), pgi.Get(1)); + GetNormalVector (surfnr, mesh.Point(pmap.Get(1)), pgi.Elem(1), n); + + for (j = 1; j <= rule.oldels.Size(); j++) + bad1 += mesh.SurfaceElement(elmap.Get(j)).CalcJacobianBadness (mesh.Points(), n); + + // check new element: + for (j = 1; j <= rule.newels.Size(); j++) + { + const Element2d & rnel = rule.newels.Get(j); + Element2d nel(rnel.GetNP()); + for (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 (j = 1; j <= rule.newels.Size(); j++) + { + const Element2d & rnel = rule.newels.Get(j); + Element2d nel(rnel.GetNP()); + nel.SetIndex (faceindex); + for (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 (j = 1; j <= rule.oldels.Size(); j++) + mesh.DeleteSurfaceElement (elmap.Get(j)); + + for (j = 1; j <= pmap.Size(); j++) + nelonnode[pmap.Get(j)] += rule.incelsonnode.Get(j); + + used[ri]++; + break; + } + } + } + } + + mesh.Compress(); + + for (ri = 0; ri < rules.Size(); ri++) + { + PrintMessage (5, "rule ", ri+1, " ", + mapped[ri], "/", used[ri], " mapped/used"); + } + + int sum = 0; + for (int i = 0; i < used.Size(); i++) + sum += used[i]; + } + + + + +} diff --git a/Netgen/libsrc/meshing/improve3.cpp b/Netgen/libsrc/meshing/improve3.cpp new file mode 100644 index 0000000000..625abaef65 --- /dev/null +++ b/Netgen/libsrc/meshing/improve3.cpp @@ -0,0 +1,1950 @@ +#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 j, k, l; + + ElementIndex ei; + PointIndex pi1, pi2; + + Point3d p1, p2, pnew; + + double bad1, bad2; + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + + TABLE<ElementIndex, PointIndex::BASE> elementsonnode(np); + ARRAY<Element*> hasonepoint; + ARRAY<Element*> hasbothpoints; + + ARRAY<ElementIndex> hasonepi, hasbothpi; + + ARRAY<double> oneperr; + ARRAY<double> elerrs (ne); + + PrintMessage (3, "CombineImprove"); + (*testout) << "Start CombineImprove" << "\n"; + + // mesh.CalcSurfacesOfNode (); + + char * savetask = multithread.task; + multithread.task = "Combine Improve"; + + int cnt = 0; + + bad1 = 0; + for (ei = 0; ei < ne; ei++) + { + double elerr = CalcBad (mesh.Points(), mesh[ei], 0); + bad1 += elerr; + elerrs[ei] = elerr; + } + + if (goal == OPT_QUALITY) + { + bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); + (*testout) << "Total badness = " << bad1 << endl; + PrintMessage (5, "Total badness = ", bad1); + } + + for (ei = 0; ei < ne; ei++) + for (j = 0; j < mesh[ei].GetNP(); j++) + elementsonnode.Add (mesh[ei][j], ei); + + INDEX_2_HASHTABLE<int> edgetested (np); + + + for (ei = 0; ei < ne; ei++) + { + if (multithread.terminate) + break; + + multithread.percent = 100.0 * (ei+1) / ne; + + if (mesh.ElementType(ei) == FIXEDELEMENT) + continue; + + for (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 } }; + + pi1 = elemi[tetedges[j][0]]; + 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 (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) + { + hasbothpoints.Append (&elem); + hasbothpi.Append (row1[k]); + } + else + { + hasonepoint.Append (&elem); + hasonepi.Append (row1[k]); + } + } + + FlatArray<ElementIndex> row2 = elementsonnode[pi2]; + for (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 + { + hasonepoint.Append (&elem); + hasonepi.Append (row2[k]); + } + } + + bad1 = 0; + for (k = 0; k < hasonepoint.Size(); k++) + bad1 += elerrs[hasonepi[k]]; + + for (k = 0; k < hasbothpoints.Size(); k++) + bad1 += elerrs[hasbothpi[k]]; + + p1 = mesh[pi1]; + p2 = mesh[pi2]; + + if (mesh.PointType(pi2) != INNERPOINT) + continue; + + if (mesh.PointType(pi1) != INNERPOINT) + pnew = p1; + else + pnew = Center (p1, p2); + + mesh[pi1] = pnew; + mesh[pi2] = pnew; + + oneperr.SetSize (hasonepoint.Size()); + bad2 = 0; + for (k = 0; k < hasonepoint.Size(); k++) + { + const Element & elem = *hasonepoint[k]; + double err = CalcTetBadness (mesh[elem[0]], mesh[elem[1]], + mesh[elem[2]], mesh[elem[3]], 0); + bad2 += err; + oneperr[k] = err; + } + + mesh[pi1] = p1; + mesh[pi2] = p2; + + + if (mesh.PointType(pi1) != INNERPOINT) + { + for (k = 0; k < hasonepoint.Size(); k++) + { + Element & elem = *hasonepoint[k]; + 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 / hasonepoint.Size() < + bad1 / (hasonepoint.Size()+hasbothpoints.Size()) ) + { + mesh[pi1] = pnew; + cnt++; + + FlatArray<ElementIndex> row = elementsonnode[pi2]; + for (k = 0; k < row.Size(); k++) + { + Element & elem = mesh[row[k]]; + elementsonnode.Add (pi1, row[k]); + for (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.Get (pi2, k) << endl; + } + + for (k = 0; k < hasonepoint.Size(); k++) + elerrs[hasonepi[k]] = oneperr[k]; + + for (k = 0; k < hasbothpoints.Size(); k++) + { + hasbothpoints[k] -> flags.illegal_valid = 0; + hasbothpoints[k] -> Delete(); + } + } + } + } + + mesh.Compress(); + mesh.MarkIllegalElements(); + + PrintMessage (5, cnt, " elements combined"); + (*testout) << "CombineImprove done" << "\n"; + + bad1 = 0; + for (ei = 0; ei < mesh.GetNE(); ei++) + bad1 += CalcBad (mesh.Points(), mesh[ei], 0); + + if (goal == OPT_QUALITY) + { + bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); + (*testout) << "Total badness = " << bad1 << endl; + + int cntill = 0; + int ne = mesh.GetNE(); + for (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(); + + 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 (int 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, -1); + OptiParameters par; + par.maxit_linsearch = 50; + par.maxit_bfgs = 20; + + pnew = Center (p1, p2); + Vector px(3); + px.Elem(1) = pnew.X(); + px.Elem(2) = pnew.Y(); + px.Elem(3) = pnew.Z(); + + if (elerrs[ei] > 0.1 * badmax) + BFGS (px, pf, par); + + bad2 = pf.Func (px); + + pnew.X() = px.Get(1); + pnew.Y() = px.Get(2); + pnew.Z() = px.Get(3); + + + 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) +{ + int j, k, l; + + (*testout) << "swapimprove" << endl; + + ElementIndex ei; + SurfaceElementIndex sei; + + int mattyp; + PointIndex pi1, pi2, pi3, pi4, pi5, pi6; + 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(); + int nse = mesh.GetNSE(); + + + // contains at least all elements at node + TABLE<ElementIndex,PointIndex::BASE> elementsonnode(np); + + ARRAY<ElementIndex> hasbothpoints; + + PrintMessage (3, "SwapImprove "); + (*testout) << "\n" << "Start SwapImprove" << endl; + + char * savetask = multithread.task; + multithread.task = "Swap Improve"; + + // mesh.CalcSurfacesOfNode (); + /* + for (i = 1; i <= GetNE(); i++) + if (volelements.Get(i).PNum(1)) + if (!LegalTet (volelements.Get(i))) + { + cout << "detected illegal tet, 1" << endl; + (*testout) << "detected illegal tet1: " << i << endl; + } + */ + + + 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 (ei = 0; ei < ne; ei++) + for (j = 0; j < mesh[ei].GetNP(); j++) + elementsonnode.Add (mesh[ei][j], ei); + + /* + BitArray illegaltet(GetNE()); + MarkIllegalElements(); + if (goal == OPT_QUALITY || goal == OPT_LEGAL) + { + int cntill = 0; + for (i = 1; i <= GetNE(); i++) + { + // if (!LegalTet (volelements.Get(i))) + if (VolumeElement(i).flags.illegal) + { + cntill++; + illegaltet.Set (i); + } + } + // (*mycout) << cntill << " illegal tets" << endl; + } + */ + + INDEX_2_HASHTABLE<int> edgeused(2 * ne + 5); + + for (ei = 0; ei < ne; ei++) + { + if (multithread.terminate) + break; + + multithread.percent = 100.0 * (ei+1) / ne; + + if (mesh.ElementType(ei) == FIXEDELEMENT) + 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 (j = 0; j < 6; j++) + { + // loop over edges + + const Element & elemi = mesh[ei]; + if (elemi.IsDeleted()) continue; + + 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 (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 (l = 0; l < elem.GetNP(); l++) + { + if (elem[l] == pi1) has1 = 1; + if (elem[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); + } + } + + bool puretet = 1; + for (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 (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 (k = 1; k < 3; k++) + { + const Element & elem = mesh[hasbothpoints[k]]; + bool has1 = 0; + for (l = 0; l < 4; l++) + if (elem[l] == pi4) + has1 = 1; + if (has1) + { + for (l = 0; l < 4; l++) + if (elem[l] != pi1 && elem[l] != pi2 && elem[l] != pi4) + pi5 = elem[l]; + } + } + + 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 (l = 0; l < 4; l++) + mesh[hasbothpoints[2]][l] = 0; + mesh[hasbothpoints[2]].Delete(); + + for (k = 0; k < 2; k++) + for (l = 0; l < 4; l++) + elementsonnode.Add (mesh[hasbothpoints[k]][l], hasbothpoints[k]); + } + } + + + if (nsuround == 4) + { + const Element & elem1 = mesh[hasbothpoints[0]]; + for (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 (k = 1; k < 4; k++) + { + const Element & elem = mesh[hasbothpoints[k]]; + bool has1 = 0; + for (l = 0; l < 4; l++) + if (elem[l] == pi4) + has1 = 1; + if (has1) + { + for (l = 0; l < 4; l++) + if (elem[l] != pi1 && elem[l] != pi2 && elem[l] != pi4) + pi5 = elem[l]; + } + } + + pi6 = 0; + for (k = 1; k < 4; k++) + { + const Element & elem = mesh[hasbothpoints[k]]; + bool has1 = 0; + for (l = 0; l < 4; l++) + if (elem[l] == pi3) + has1 = 1; + if (has1) + { + for (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 (k = 0; k < 4; k++) + for (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 (k = 0; k < 4; k++) + for (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 (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 (l = 2; l < nsuround; l++) + { + int oldpi = suroundpts[l-1]; + int newpi = 0; + + for (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; + } + } + } + + + double bad1 = 0, bad2; + for (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 (l = 0; l < nsuround; l++) + { + bad2 = 0; + + for (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 (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 (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 (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 (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; +} + + + + + + + + +/* + 2 -> 3 conversion +*/ + + + +void MeshOptimize3d :: SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal) +{ + int j, k, l; + // INDEX_2 i2; + ElementIndex ei, eli1, eli2, elnr; + SurfaceElementIndex sei; + PointIndex pi1, pi2, pi3, pi4, pi5; + + int mattyp; + int cnt = 0; + + Element el21(TET), el22(TET), el31(TET), el32(TET), el33(TET); + + 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; + + // find elements on node + + for (ei = 0; ei < ne; ei++) + for (j = 0; j < mesh[ei].GetNP(); j++) + elementsonnode.Add (mesh[ei][j], ei); + + for (sei = 0; sei < nse; sei++) + for (j = 0; j < 3; j++) + belementsonnode.Add (mesh[sei][j], sei); + + // cout << "main loop" << endl; + + for (eli1 = 0; eli1 < mesh.GetNE(); 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; + + + + for (j = 0; j < 4; j++) + { + // loop over faces + + Element & elem = mesh[eli1]; + // if (elem[0] < PointIndex::BASE) continue; + if (elem.IsDeleted()) continue; + + 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 (k = 0; k < belementsonnode[pi1].Size(); k++) + { + const Element2d & bel = + mesh[belementsonnode[pi1][k]]; + + bool bface1 = 1; + for (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 (k = 0; k < row.Size(); k++) + { + 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 (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) + { + // (*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 (l = 0; l < 4; l++) + { + elementsonnode.Add (el31[l], eli1); + elementsonnode.Add (el32[l], eli2); + elementsonnode.Add (el33[l], neli); + } + + break; + } + } + } + } + } + } + + // cout << "loop done" << endl; + + 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/Netgen/libsrc/meshing/improve3.hpp b/Netgen/libsrc/meshing/improve3.hpp new file mode 100644 index 0000000000..9b5b2c9bec --- /dev/null +++ b/Netgen/libsrc/meshing/improve3.hpp @@ -0,0 +1,50 @@ +#ifndef FILE_IMPROVE3 +#define FILE_IMPROVE3 + + + + +/// +class MeshOptimize3d +{ +public: + void CombineImprove (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY); + void SplitImprove (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY); + void SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY); + void SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY); +}; + + + +extern double CalcBad (const Mesh::T_POINTS & points, const Element & elem, + double h); + +extern double CalcTotalBad (const Mesh::T_POINTS & points, + const Mesh::T_VOLELEMENTS & elements); + +extern int WrongOrientation (const Mesh::T_POINTS & points, const Element & el); + + +/* Functional depending of inner point inside triangular surface */ + + + +class PointFunction1 : public MinFunction +{ + Mesh::T_POINTS & points; + const ARRAY<INDEX_3> & faces; + double h; +public: + PointFunction1 (Mesh::T_POINTS & apoints, + const ARRAY<INDEX_3> & afaces, + 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; +}; + + + +#endif diff --git a/Netgen/libsrc/meshing/localh.cpp b/Netgen/libsrc/meshing/localh.cpp new file mode 100644 index 0000000000..62025737f3 --- /dev/null +++ b/Netgen/libsrc/meshing/localh.cpp @@ -0,0 +1,682 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + +GradingBox :: GradingBox (const double * ax1, const double * ax2) +{ + int i; + + h2 = 0.5 * (ax2[0] - ax1[0]); + for (i = 0; i <= 2; i++) + { + /* + x1[i] = ax1[i]; + x2[i] = ax2[i]; + */ + xmid[i] = 0.5 * (ax1[i] + ax2[i]); + } + + /* + (*testout) << "new box: " << xmid[0] << "-" << xmid[1] << "-" << xmid[2] + << " h = " << (x2[0] - x1[0]) << endl; + */ + + for (i = 0; i < 8; i++) + childs[i] = NULL; + father = NULL; + + flags.cutboundary = 0; + flags.isinner = 0; + flags.oldcell = 0; + flags.pinner = 0; + + // hopt = x2[0] - x1[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() +{ + int i; + for (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; + int i; + + boundingbox = Box3d (pmin, pmax); + grading = agrading; + + // a small enlargement, non-regular points + double val = 0.0879; + for (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 (i = 1; i <= 2; i++) + if (x2[i] - x1[i] > hmax) + hmax = x2[i] - x1[i]; + + for (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; + int i; + for (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); + } + /* + Point3d np; + int i1, i2, i3; + for (i1 = -1; i1 <= 1; i1++) + for (i2 = -1; i2 <= 1; i2++) + for (i3 = -1; i3 <= 1; i3++) + { + np.X() = p.X() + hbox * i1; + np.Y() = p.Y() + hbox * i2; + np.Z() = p.Z() + hbox * i3; + + SetH (np, hnp); + } + */ +} + + + +double LocalH :: GetH (const Point3d & x) const +{ + const GradingBox * box = root; + const GradingBox * nbox; + int childnr; + + while (1) + { + 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; + nbox = box->childs[childnr]; + if (nbox) + box = nbox; + else + { + // (*testout) << "diam = " << (box->x2[0] - box->x1[0]) + // << " h = " << box->hopt << endl; + 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; + /* + if (pmax.X() < box->x1[0] || pmin.X() > box->x2[0] || + pmax.Y() < box->x1[1] || pmin.Y() > box->x2[1] || + pmax.Z() < box->x1[2] || pmin.Z() > box->x2[2]) + return 1e8; + */ + + + double hmin = 2 * box->h2; // box->x2[0] - box->x1[0]; + int i; + + for (i = 0; i <= 7; i++) + { + if (box->childs[i]) + { + double hi = GetMinHRec (pmin, pmax, box->childs[i]); + if (hi < hmin) + hmin = hi; + } + } + + 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; + /* + if (pmax.X() < box->x1[0] || pmin.X() > box->x2[0] || + pmax.Y() < box->x1[1] || pmin.Y() > box->x2[1] || + pmax.Z() < box->x1[2] || pmin.Z() > box->x2[2]) + 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 ( // int (*sameside)(const Point3d & p1, const Point3d & p2), + AdFront3 * adfront, + int (*testinner)(const Point3d & p1)) +{ + int i, j; + + int nf = adfront->GetNF(); + + for (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 (i = 1; i <= nf; i++) + { + faceinds.Elem(i) = i; + adfront->GetFaceBoundingBox(i, faceboxes.Elem(i)); + } + + for (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; + + int i, j; + + 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); + + + static ARRAY<int> faceused; + static ARRAY<int> faceused2; + static ARRAY<int> facenotused; + + faceused.SetSize(0); + facenotused.SetSize(0); + faceused2.SetSize(0); + + for (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 (j = 1; j <= faceused.Size(); j++) + faceinds.Elem(j) = faceused.Get(j); + for (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; + } + + int nf = faceused.Size(); + for (i = 0; i < 8; i++) + FindInnerBoxesRec2 (box->childs[i], adfront, faceboxes, faceinds, nf); +} + + + + + + + + + + + + +/* +void LocalH :: FindInnerBoxes ( // int (*sameside)(const Point3d & p1, const Point3d & p2), + AdFront3 * adfront, + int (*testinner)(const Point3d & p1)) +{ + int i; + for (i = 1; i <= boxes.Size(); i++) + boxes.Elem(i)->flags.isinner = 0; + + root->flags.isinner = 0; + + Point3d rpmid(root->xmid[0], root->xmid[1], root->xmid[2]); + Point3d rx2 = rpmid + Vec3d (root->h2, root->h2, root->h2); + + 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; + + + for (i = 2; i <= boxes.Size(); i++) + { + GradingBox * box = boxes.Elem(i); + GradingBox * father = box -> father; + + Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]); + Vec3d v(box->h2, box->h2, box->h2); + Point3d x1 = c-v; + Point3d x2 = c+v; + + + 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)) + 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; + } + } + // FindInnerBoxesRec (inner, root); +} +*/ + + +void LocalH :: FindInnerBoxesRec ( int (*inner)(const Point3d & p), + GradingBox * box) +{ + int i; + if (box->flags.cutboundary) + { + for (i = 0; i < 8; i++) + if (box->childs[i]) + FindInnerBoxesRec (inner, box->childs[i]); + } + else + { + if (inner (Point3d (box->xmid[0], box->xmid[1], box->xmid[2]))) + 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 () +{ + int nb = boxes.Size(); + int i; + // (*testout) << "old boxes: " << nb << endl; + for (i = 1; i <= nb; i++) + { + GradingBox * box = boxes.Get(i); + // double h = box->x2[0] - box->x1[0]; + double h = box->hopt; + Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]); + // (*testout) << " i = " << i + // << " c = " << c << " h = " << h << endl; + + 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<Point3d> & points) +{ + int i, nb = boxes.Size(); + + for (i = 1; i <= nb; i++) + { + GradingBox * box = boxes.Get(i); + /* + if (box->flags.pinner) + points.Append (box->randomip); + */ + // if (box->flags.pinner) + if (box->flags.isinner) + { + Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]); + points.Append (c); + /* + cout << "add point " << c << "; h = " << box->hopt + << "; max-min = " << (box->x2[0]-box->x1[0]) << endl; + */ + } + } +} + + + +void LocalH :: GetOuterPoints (ARRAY<Point3d> & points) +{ + int i, nb = boxes.Size(); + + for (i = 1; i <= nb; i++) + { + GradingBox * box = boxes.Get(i); + if (!box->flags.isinner && + !box->flags.cutboundary) + { + Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]); + points.Append (c); + } + } +} + + + +void LocalH :: Convexify () +{ + ConvexifyRec (root); +} + +void LocalH :: ConvexifyRec (GradingBox * box) +{ + Point3d center(box->xmid[0], box->xmid[1], box->xmid[2]); + Point3d hp; + + double size = 2 * box->h2; // box->x2[0] - box->x1[0]; + double dx = 0.6 * size; + + double maxh = box->hopt; + int i; + + + + for (i = 1; i <= 6; i++) + { + hp = center; + switch (i) + { + case 1: hp.X() += dx; break; + case 2: hp.X() -= dx; break; + case 3: hp.Y() += dx; break; + case 4: hp.Y() -= dx; break; + case 5: hp.Z() += dx; break; + case 6: hp.Z() -= dx; break; + } + + double hh = GetH (hp); + if (hh > maxh) maxh = hh; + } + + if (maxh < 0.95 * box->hopt) + SetH (center, maxh); + + for (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/Netgen/libsrc/meshing/localh.hpp b/Netgen/libsrc/meshing/localh.hpp new file mode 100644 index 0000000000..9d6ea35a50 --- /dev/null +++ b/Netgen/libsrc/meshing/localh.hpp @@ -0,0 +1,143 @@ +#ifndef LOCALH +#define LOCALH + +/**************************************************************************/ +/* File: localh.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 29. Jan. 97 */ +/**************************************************************************/ + + + + +/// box for grading +class GradingBox +{ + /* + /// xmin + float x1[3]; + /// xmax + float x2[3]; + */ + /// xmid + float xmid[3]; + /// half edgelength + float h2; + /// + GradingBox * childs[8]; + /// + GradingBox * father; + /// + double hopt; + /// + struct + { + unsigned int cutboundary:1; + unsigned int isinner:1; + unsigned int oldcell:1; + unsigned int pinner:1; + } flags; +public: + /// + GradingBox (const double * ax1, const double * ax2); + /// + void DeleteChilds(); + /// + 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(); + /// + void Delete(); + /// + 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); } + + /// find inner boxes + void FindInnerBoxes ( // int (*sameside)(const Point3d & p1, const Point3d & p2), + class AdFront3 * adfront, + int (*testinner)(const Point3d & p1)); + + /// clears all flags + void ClearFlags () + { ClearFlagsRec(root); } + + /// widen refinement zone + void WidenRefinement (); + + /// get points in inner elements + void GetInnerPoints (ARRAY<Point3d> & points); + + /// get points in outer closure + void GetOuterPoints (ARRAY<Point3d> & 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 SetInnerBoxesRec (GradingBox * box); + + /// + void ClearFlagsRec (GradingBox * box); + + /// + void ConvexifyRec (GradingBox * box); +}; + + +#endif diff --git a/Netgen/libsrc/meshing/meshclass.cpp b/Netgen/libsrc/meshing/meshclass.cpp new file mode 100644 index 0000000000..668c1f3d6e --- /dev/null +++ b/Netgen/libsrc/meshing/meshclass.cpp @@ -0,0 +1,4165 @@ +#include <mystdlib.h> + +#include "meshing.hpp" + +namespace netgen +{ + +Mesh :: Mesh () + : ident (*this) + +{ + boundaryedges = NULL; + surfelementht = NULL; + segmentht = NULL; + + lochfunc = NULL; + mglevels = 1; + elementsearchtree = NULL; + elementsearchtreets = NextTimeStamp(); + majortimestamp = timestamp = NextTimeStamp(); + hglob = 1e10; + numvertices = -1; + dimension = 3; + topology = new MeshTopology (*this); + curvedelems = new CurvedElements (*this); + clusters = new AnisotropicClusters (*this); + + // volelements.SetName ("Volume Elements"); + // surfelements.SetName ("Surface Elements"); + // points.SetName ("Mesh Points"); +} + +Mesh :: ~Mesh() +{ + // DeleteMesh(); + delete lochfunc; + delete boundaryedges; + delete surfelementht; + delete segmentht; + delete curvedelems; + delete clusters; + delete topology; +} + +void Mesh :: DeleteMesh() +{ + points.SetSize(0); + ptyps.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); + + ident.Delete(); + + delete topology; + topology = new MeshTopology (*this); + delete curvedelems; + curvedelems = new CurvedElements (*this); + delete clusters; + clusters = new AnisotropicClusters (*this); + + timestamp = NextTimeStamp(); +} + + + +PointIndex Mesh :: AddPoint (const Point3d & p, int layer) +{ + NgLock lock(mutex); + lock.Lock(); + + timestamp = NextTimeStamp(); + + if (ptyps.Size() == points.Size()) + ptyps.Append (INNERPOINT); + + PointIndex pi = points.Size() + PointIndex::BASE; + points.Append ( MeshPoint (p, layer) ); + + lock.UnLock(); + + return pi; +} + + +SegmentIndex Mesh :: AddSegment (const Segment & s) +{ + NgLock lock(mutex); + lock.Lock(); + timestamp = NextTimeStamp(); + + int maxn = max2 (s.p1, s.p2); + 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.p1] > EDGEPOINT) ptyps[s.p1] = EDGEPOINT; + if (ptyps[s.p2] > EDGEPOINT) ptyps[s.p2] = EDGEPOINT; + + 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 i; + int maxn = el[0]; + for (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; + } + + for (i = 0; i < el.GetNP(); i++) + if (ptyps[el[i]] > SURFACEPOINT) + ptyps[el[i]] = SURFACEPOINT; + + SurfaceElementIndex si = surfelements.Size(); + surfelements.Append (el); + + lock.UnLock(); + return si; +} + + +ElementIndex Mesh :: AddVolumeElement (const Element & el) +{ + NgLock lock(mutex); + lock.Lock(); + + int i; + + int maxn = el[0]; + for (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; + } + + + int ve = volelements.Size(); + + volelements.Append (el); + volelements.Last().flags.illegal_valid = 0; + + while (volelements.Size() > eltyps.Size()) + eltyps.Append (FREEELEMENT); + + timestamp = NextTimeStamp(); + + lock.UnLock(); + return ve; +} + + + + + + +void Mesh :: Save (const char * filename) const +{ + int i, j; + + double scale = 1; // globflags.GetNumFlag ("scale", 1); + int inverttets = 0; // globflags.GetDefineFlag ("inverttets"); + int invertsurf = 0; // globflags.GetDefineFlag ("invertsurfacemesh"); + + ofstream outfile(filename); + + + outfile << "mesh3d" << "\n"; + + outfile << "dimension\n" << GetDimension() << "\n"; + + outfile << "\n"; + outfile << "# surfnr bcnr domin domout np p1 p2 p3" + << "\n"; + + outfile << "surfaceelementsgi" << "\n"; + // 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]; + } + + for (j = 1; j <= sel.GetNP(); j++) + { + outfile.width(7); + outfile << " " << sel.GeomInfoPi(j).trignum; + } + outfile << endl; + } + + 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++) + { + outfile.width(8); + outfile << el[j]; + } + outfile << "\n"; + } + + + outfile << "\n" << "\n"; + outfile << " surf1 surf2 p1 p2" << "\n"; + outfile << "edgesegmentsgi2" << "\n"; + outfile << GetNSeg() << "\n"; + + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment (i); + outfile.width(8); + outfile << seg.si; + outfile.width(8); + outfile << 0; + outfile.width(8); + outfile << seg.p1; + outfile.width(8); + outfile << seg.p2; + outfile << " "; + outfile.width(8); + outfile << seg.geominfo[0].trignum; + outfile << " "; + outfile.width(8); + outfile << seg.geominfo[1].trignum << endl; + + outfile << " "; + outfile.width(8); + outfile << seg.surfnr1+1; + outfile << " "; + outfile.width(8); + outfile << seg.surfnr2+1; + outfile << " "; + outfile.width(8); + outfile << seg.edgenr; + // outfile << seg.epgeominfo[0].edgenr; + /* + outfile.width(8); + outfile << seg.epgeominfo[0].lefttrig; + outfile.width(8); + outfile << seg.epgeominfo[0].righttrig; + */ + outfile << " "; + outfile.width(12); + outfile << seg.epgeominfo[0].dist; + outfile << " "; + outfile.width(8); + outfile << seg.epgeominfo[1].edgenr; + /* + outfile.width(8); + outfile << seg.epgeominfo[1].lefttrig; + outfile.width(8); + outfile << seg.epgeominfo[1].righttrig; + */ + 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 = 1; pi <= GetNP(); pi++) + { + outfile.width(22); + outfile << (*this)[pi].X()/scale << " "; + outfile.width(22); + outfile << (*this)[pi].Y()/scale << " "; + outfile.width(22); + outfile << (*this)[pi].Z()/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"; + } + } + } + + 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; + } + + // delete houtfile; +} + + +void Mesh :: Load (const char * filename) +{ + 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"); + + + ifstream infile(filename); + if (!infile.good()) + { + throw NgException ("mesh file not found"); + // cerr << "mesh file not found !!" << endl; + // return; + } + + facedecoding.SetSize(0); + + while (infile.good()) + { + infile >> str; + + if (strcmp (str, "dimension") == 0) + { + infile >> dimension; + } + + if (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--; + + 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)); + 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); + + if (invertsurf) + tri.Invert(); + + AddSurfaceElement (tri); + } + } + + if (strcmp (str, "surfaceelementsgi") == 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--; + + 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)); + 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); + + for (j = 1; j <= nep; j++) + infile >> tri.GeomInfoPi(j).trignum; + + if (invertsurf) + 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.p1 >> seg.p2; + AddSegment (seg); + } + } + + if (strcmp (str, "edgesegmentsgi") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + Segment seg; + int hi; + infile >> seg.si >> hi >> seg.p1 >> seg.p2 + >> seg.geominfo[0].trignum + >> seg.geominfo[1].trignum; + 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.p1 >> seg.p2 + >> seg.geominfo[0].trignum + >> seg.geominfo[1].trignum + >> seg.surfnr1 >> seg.surfnr2 + >> seg.epgeominfo[0].edgenr + // >> seg.epgeominfo[0].lefttrig + // >> seg.epgeominfo[0].righttrig + >> seg.epgeominfo[0].dist + >> seg.epgeominfo[1].edgenr + // >> seg.epgeominfo[1].lefttrig + // >> seg.epgeominfo[1].righttrig + >> seg.epgeominfo[1].dist; + seg.edgenr = seg.epgeominfo[0].edgenr; + + 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, "materials") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + int nr; + string mat; + infile >> nr >> mat; + SetMaterial (nr, mat.c_str()); + } + } + + strcpy (str, ""); + } + + CalcSurfacesOfNode (); + // BuildConnectedNodes (); + topology -> Update(); + clusters -> Update(); + + SetNextMajorTimeStamp(); + // PrintMemInfo (cout); +} + + + +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 :: CalcSurfacesOfNode () +{ + int i, j, k; + SurfaceElementIndex sei; + + surfacesonnode.SetSize (GetNP()); + if (boundaryedges) + delete boundaryedges; + if (surfelementht) + delete surfelementht; + if (segmentht) + delete segmentht; + + boundaryedges = new INDEX_2_CLOSED_HASHTABLE<int> + (3 * (GetNSE() + GetNOpenElements()) + GetNSeg() + 1); + surfelementht = new INDEX_3_HASHTABLE<int> (GetNSE()/4 + 1); + segmentht = new INDEX_2_HASHTABLE<int> (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); + + 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 (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, sel.GetIndex()); + } + + int np = GetNP(); + ptyps.SetSize(np); + ptyps = INNERPOINT; + + if (GetNFD() == 0) // || GetFaceDescriptor(1).SurfNr() == 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]; + ptyps[pi] = FIXEDPOINT; + } + } + } + else + { + for (sei = 0; sei < GetNSE(); sei++) + { + const Element2d & sel = surfelements[sei]; + if (sel.IsDeleted()) continue; + for (j = 0; j < sel.GetNP(); j++) + { + int pi = sel[j]; + int ns = surfacesonnode[pi].Size(); + if (ns == 1) + ptyps[pi] = SURFACEPOINT; + if (ns == 2) + ptyps[pi] = EDGEPOINT; + if (ns >= 3) + ptyps[pi] = FIXEDPOINT; + } + } + } + + for (i = 0; i < segments.Size(); i++) + { + const Segment & seg = segments[i]; + for (j = 1; j <= 2; j++) + { + PointIndex hi = (j == 1) ? seg.p1 : seg.p2; + + if (ptyps[hi] == INNERPOINT || + ptyps[hi] == SURFACEPOINT) + ptyps[hi] = EDGEPOINT; + } + } + + + for (i = 0; i < lockedpoints.Size(); i++) + ptyps[lockedpoints[i]] = 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); + + ptyps[sel[j]] = FIXEDPOINT; + } + } + + eltyps.SetSize (GetNE()); + eltyps = FREEELEMENT; + + for (i = 0; i < GetNSeg(); i++) + { + const Segment & seg = segments[i]; + INDEX_2 i2(seg.p1, seg.p2); + i2.Sort(); + + boundaryedges -> Set (i2, 2); + segmentht -> Set (i2, 1); + } +} + + +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)) + { + ptyps.Elem(i) = FIXEDPOINT; + } +} + + +void Mesh :: FindOpenElements (int dom) +{ + int i, ii, j, k, l; + PointIndex pi; + SurfaceElementIndex sei; + Element2d hel; + + + + if (1) + { // nodebased + + int np = GetNP(); + int ne = GetNE(); + int nse = GetNSE(); + + ARRAY<int,PointIndex::BASE> numonpoint(np); + + Element2d hel; + + numonpoint = 0; + /* + for (i = 1; i <= np; i++) + numonpoint.Elem(i) = 0; + */ + ElementIndex ei; + for (ei = 0; ei < ne; ei++) + { + const Element & el = (*this)[ei]; + 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 (j = 0; j < el.GetNP(); j++) + numonpoint[el[j]]++; + } + TABLE<ElementIndex,PointIndex::BASE> elsonpoint(numonpoint); + for (ei = 0; ei < ne; ei++) + { + const Element & el = (*this)[ei]; + 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 (j = 0; j < el.GetNP(); j++) + elsonpoint.Add (el[j], ei); + } + + numonpoint = 0; + for (i = 0; i < nse; i++) + { + hel = surfelements[i]; + hel.NormalizeNumbering(); + numonpoint[hel[0]]++; + } + + TABLE<SurfaceElementIndex,PointIndex::BASE> selsonpoint(numonpoint); + for (i = 0; i < nse; i++) + { + hel = surfelements[i]; + hel.NormalizeNumbering(); + selsonpoint.Add (hel[0], i); + } + + + INDEX_3_CLOSED_HASHTABLE<INDEX_2> faceht(100); + openelements.SetSize(0); + + for (pi = PointIndex::BASE; + pi < np+PointIndex::BASE; pi++) + { + 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 (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 (i = 1; 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 (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); + } + } + } + } + + else if (GetNE() || 1) + { + // new version, general elemetns + // hash index: pnum1-3 + // hash data : domain nr, pnum4 + + openelements.SetSize(0); + + + const int steps = 4; + + for (k = 0; k < steps; k++) + { + + INDEX_3_CLOSED_HASHTABLE<INDEX_2> faceht( (5 * GetNE() + 2 * GetNSE() ) / steps +1); + + for (i = 1; i <= GetNSE(); i++) + { + hel = SurfaceElement(i); + int ind = hel.GetIndex(); + + + if (GetFaceDescriptor(ind).DomainIn() && + (dom == 0 || dom == GetFaceDescriptor(ind).DomainIn()) ) + { + hel.Invert(); + hel.NormalizeNumbering(); + if (hel.PNum(1) % steps == k) + { + INDEX_3 i3(hel.PNum(1), hel.PNum(2), hel.PNum(3)); + 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.NormalizeNumbering(); + if (hel.PNum(1) % steps == k) + { + INDEX_3 i3(hel.PNum(1), hel.PNum(2), hel.PNum(3)); + INDEX_2 i2 (GetFaceDescriptor(ind).DomainOut(), + (hel.GetNP() == 3) + ? PointIndex(0) + : hel.PNum(4)); + faceht.Set (i3, i2); + } + } + } + + for (i = 1; i <= GetNE(); i++) + { + const Element & el = VolumeElement(i); + + if (dom == 0 || el.GetIndex() == dom) + { + for (j = 1; j <= el.GetNFaces(); j++) + { + el.GetFace (j, hel); + + hel.NormalizeNumbering(); + if (hel.PNum(1) % steps != k) + continue; + + INDEX_3 i3(hel.PNum(1), hel.PNum(2), hel.PNum(3)); + + int pos = faceht.Position (i3); + if (pos) + { + INDEX_2 i2; + faceht.GetData (pos, i2); + if (i2.I1() == el.GetIndex()) + { + i2.I1() = 0; + faceht.SetData (pos, i2); + } + else + { + if (i2.I1() == 0) + PrintSysError ("more elements on face"); + } + } + else + { + hel.Invert(); + hel.NormalizeNumbering(); + INDEX_3 i3(hel.PNum(1), hel.PNum(2), hel.PNum(3)); + INDEX_2 i2(el.GetIndex(), + (hel.GetNP() == 3) + ? PointIndex(0) + : hel.PNum(4)); + faceht.Set (i3, i2); + } + } + } + } + + for (i = 1; i <= faceht.Size(); i++) + if (faceht.UsedPos (i)) + { + INDEX_3 i3; + INDEX_2 i2; + faceht.GetData (i, i3, i2); + if (i2.I1() != 0) + { + Element2d tri; + tri.SetType ( (i2.I2() == 0) ? TRIG : QUAD); + for (l = 1; l <= 3; l++) + tri.PNum(l) = i3.I(l); + tri.PNum(4) = i2.I2(); + tri.SetIndex (i2.I1()); + + tri.Invert(); + + openelements.Append (tri); + } + } + /* + cout << "FindOpenElements, mem = "; + faceht.PrintMemInfo (cout); + */ + } + + + + + /* + // open hashing version: + + INDEX_3_HASHTABLE<INDEX_2> faceht(4 * GetNE()+GetNSE()+1); + + for (i = 1; i <= GetNSE(); i++) + { + Element2d hel = SurfaceElement(i); + int ind = hel.GetIndex(); + + + if (GetFaceDescriptor(ind).DomainIn() && + (dom == 0 || dom == GetFaceDescriptor(ind).DomainIn()) ) + { + hel.NormalizeNumbering(); + INDEX_3 i3(hel.PNum(1), hel.PNum(2), hel.PNum(3)); + INDEX_2 i2 (GetFaceDescriptor(ind).DomainIn(), + (hel.GetNP() == 3) ? 0 : hel.PNum(4)); + faceht.Set (i3, i2); + } + if (GetFaceDescriptor(ind).DomainOut() && + (dom == 0 || dom == GetFaceDescriptor(ind).DomainOut()) ) + { + hel.Invert(); + hel.NormalizeNumbering(); + INDEX_3 i3(hel.PNum(1), hel.PNum(2), hel.PNum(3)); + INDEX_2 i2 (GetFaceDescriptor(ind).DomainOut(), + (hel.GetNP() == 3) ? 0 : hel.PNum(4)); + faceht.Set (i3, i2); + } + } + + for (i = 1; i <= GetNE(); i++) + { + const Element & el = VolumeElement(i); + // INDEX_3 i3; + + if (dom == 0 || el.GetIndex() == dom) + { + for (j = 1; j <= el.GetNFaces(); j++) + { + Element2d hel; + el.GetFace (j, hel); + hel.Invert(); + + hel.NormalizeNumbering(); + INDEX_3 i3(hel.PNum(1), hel.PNum(2), hel.PNum(3)); + + if (faceht.Used (i3)) + { + INDEX_2 i2 = faceht.Get(i3); + if (i2.I1() == el.GetIndex()) + { + i2.I1() = 0; + faceht.Set (i3, i2); + } + else + { + if (i2.I1() == 0) + PrintSysError ("more elements on face"); + } + } + else + { + hel.Invert(); + hel.NormalizeNumbering(); + INDEX_3 i3(hel.PNum(1), hel.PNum(2), hel.PNum(3)); + INDEX_2 i2(el.GetIndex(), + (hel.GetNP() == 3) ? 0 : hel.PNum(4)); + faceht.Set (i3, i2); + } + } + } + } + + + openelements.SetSize(0); + for (i = 1; i <= faceht.GetNBags(); i++) + for (j = 1; j <= faceht.GetBagSize(i); j++) + { + INDEX_3 i3; + INDEX_2 i2; + faceht.GetData (i, j, i3, i2); + if (i2.I1() != 0) + { + Element2d tri; + tri.SetNP ( (i2.I2() == 0) ? 3 : 4); + for (k = 1; k <= 3; k++) + tri.PNum(k) = i3.I(k); + tri.PNum(4) = i2.I2(); + tri.SetIndex (i2.I1()); + + openelements.Append (tri); + } + } + */ + + } + else + { + for (i = 1; i <= GetNSE(); i++) + { + Element2d hel = SurfaceElement(i); + int ind = SurfaceElement(i).GetIndex(); + + if (GetFaceDescriptor(ind).DomainIn()) + openelements.Append (hel); + if (GetFaceDescriptor(ind).DomainOut()) + { + hel.Invert(); + openelements.Append (hel); + } + } + } + + + int cnt3 = 0, cnt4 = 0; + for (i = 1; i <= openelements.Size(); i++) + if (openelements.Elem(i).GetNP() == 3) + cnt3++; + else + cnt4++; + + + MyStr treequad; + if (cnt4) + treequad = MyStr(" (") + MyStr(cnt3) + MyStr (" + ") + + MyStr(cnt4) + MyStr(")"); + + PrintMessage (5, openelements.Size(), treequad, " open elements"); + + + 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()+PointIndex::BASE) + ptyps[pi] = FIXEDPOINT; + } + } + + + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment(i); + INDEX_2 i2(seg.p1, seg.p2); + i2.Sort(); + + if (!boundaryedges->Used (i2)) + cerr << "WARNING: no boundedge, but seg edge: " << i2 << endl; + + boundaryedges -> Set (i2, 2); + segmentht -> Set (i2, 1); + } +} + +int Mesh :: HasOpenQuads () const +{ + int i; + int no = GetNOpenElements(); + for (i = 1; i <= no; i++) + if (OpenElement(i).GetNP() == 4) + return 1; + return 0; +} + + + + + +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.p1, seg.p2); + 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.p2, seg.p1); + 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 (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 (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.p1 = i2.I1(); + seg.p2 = 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.p1 == el.PNum(k)) + seg.geominfo[0] = el.GeomInfoPi(k); + if (seg.p2 == 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.p1 << " - " << seg.p2 + << " len = " << Dist (Point(seg.p1), Point(seg.p2)) + << 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.p1) = EDGEPOINT; + ptyps.Elem(seg.p2) = EDGEPOINT; + } + for (i = 1; i <= GetNOpenSegments(); i++) + { + const Segment & seg = GetOpenSegment (i); + ptyps.Elem(seg.p1) = EDGEPOINT; + ptyps.Elem(seg.p2) = 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.p1); + frontpoints.Set (seg.p2); + } + + 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(); + } + } + 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 (i = 1; i <= GetNOpenElements(); i++) + { + const Element2d & face = OpenElement(i); + for (j = 1; j <= face.GetNP(); j++) + dist[face.PNum(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++) + { + 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]]; + + 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) + ptyps[pi] = 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) +{ + // 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) +{ + // 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 :: 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 () +{ + if (!lochfunc) + { + Point3d pmin, pmax; + GetBox (pmin, pmax); + SetLocalH (pmin, pmax, mparam.grading); + } + + PrintMessage (3, + "CalcLocalH: ", + GetNP(), " Points ", + GetNE(), " Elements ", + GetNSE(), " Surface Elements"); + + + int i; + for (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 (i = 0; i < GetNSeg(); i++) + { + const Segment & seg = segments[i]; + const Point3d & p1 = points[seg.p1]; + const Point3d & p2 = points[seg.p2]; + /* + INDEX_2 i21(seg.p1, seg.p2); + INDEX_2 i22(seg.p2, seg.p1); + if (identifiedpoints) + if (!identifiedpoints->Used (i21) && !identifiedpoints->Used (i22)) + */ + if (!ident.UsedSymmetric (seg.p1, seg.p2)) + { + 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 :: CalcLocalHFromSurfaceCurvature (double elperr) +{ + PrintMessage (3, "Calculating local h from Surface curvature"); + + if (!lochfunc) + { + Point3d pmin, pmax; + GetBox (pmin, pmax); + + SetLocalH (pmin, pmax, mparam.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.p1, seg.p2); + 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.p1); + const Point3d & p2 = Point(seg.p2); + 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).p1); + linepoint.Set (LineSegment(i).p2); + } + + 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.p1), Point(seg.p2), loch); + break; + } + } +} + + +void Mesh :: LoadLocalMeshSize (istream & msf) +{ + PrintMessage (3, "Load local mesh-size"); + int i, nmsp, nmsl; + msf >> nmsp; + for (i = 1; i <= nmsp; i++) + { + Point3d pi; + double hi; + msf >> pi.X() >> pi.Y() >> pi.Z(); + msf >> hi; + RestrictLocalH (pi, hi); + } + msf >> nmsl; + for (i = 1; i <= nmsl; i++) + { + Point3d p1, p2; + double hi; + msf >> p1.X() >> p1.Y() >> p1.Z(); + msf >> p2.X() >> p2.Y() >> p2.Z(); + msf >> hi; + RestrictLocalHLine (p1, p2, hi); + } +} + + + +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 (ptyps[pi] <= ptyp) + { + pmin.SetToMin ( (*this) [pi] ); + pmax.SetToMax ( (*this) [pi] ); + } +} + + + + +double Mesh :: ElementError (int eli) 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); +} + +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<Point3d> 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].p1 == -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.p1); + pused.Set (seg.p2); + } + + 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 doesn´t work for identified points ! + if (identifiedpoints) + { + for (i = 1; i <= identifiedpoints->GetNBags(); i++) + if (identifiedpoints->GetBagSize(i)) + { + pused.Set (); + break; + } + } + */ + // pused.Set(); + + + int npi = PointIndex::BASE-1; + + for (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.p1 = op2np[seg.p1]; + seg.p2 = op2np[seg.p2]; + } + + 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]]; + + + + 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); + int i, j; + INDEX_2 i2; + int err = 0; + + + for (i = 1; i <= nf; i++) + { + const Element2d & sel = OpenElement(i); + + for (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); + /* + + if (edges.Used(i2)) + { + int hi; + hi = edges.Get(i2); + if (hi != 1) + err = 1; + edges.Set(i2, 2); + cnt2++; + } + else + { + Swap (i2.I1(), i2.I2()); + edges.Set(i2, 1); + cnt1++; + } + */ + } + } + + + /* + if (cnt1 != cnt2) + err = 2; + */ + + for (i = 1; i <= edges.GetNBags(); i++) + for (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"); + err = 2; + } + } + + return err; +} + + + +int Mesh :: CheckOverlappingBoundary () +{ + int i, j, k; + + Point3d pmin, pmax; + GetBox (pmin, pmax); + Box3dTree setree(pmin, pmax); + ARRAY<int> inters; + int overlap = 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)); + + const Point3d *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; + + 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; + + + /* + 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; + } + } + } + + 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 +{ + // return 1; + // Test, whether 4 points have a common surface plus + // at least 4 edges at the boundary + + int i, j, k; + + // non-tets are always legal + if (el.GetType() != TET) + { + el.SetLegal (1); + return 1; + } + + // element has at least 2 inner points ---> legal + int cnti = 0; + for (j = 1; j <= 4; j++) + if (PointType(el.PNum(j)) == INNERPOINT) + cnti++; + if (cnti >= 2) + { + el.SetLegal (1); + return 1; + } + + // which faces are boundary faces ? + Element2d face; + int bface[4]; + + for (i = 1; i <= 4; i++) + { + el.GetFace (i, face); + INDEX_3 i3 (face.PNum(1), face.PNum(2), face.PNum(3)); + i3.Sort(); + bface[i-1] = surfelementht->Used (i3); + } + + int bedge[4][4]; + int segedge[4][4]; + for (i = 1; i <= 4; i++) + for (j = 1; j < i; j++) + { + INDEX_2 i2(el.PNum(i), el.PNum(j)); + i2.Sort(); + + int sege = 0, be = 0; + + if (boundaryedges -> Used(i2)) + { + int val = boundaryedges -> Get(i2); + be = 1; + if (val == 2) + sege = 1; + } + + segedge[j-1][i-1] = + segedge[i-1][j-1] = sege; + + bedge[j-1][i-1] = + bedge[i-1][j-1] = be; + } + + + // two boundary faces and no edge is illegal + for (i = 0; i < 3; i++) + for (j = i+1; j < 4; j++) + { + if (bface[i] && bface[j]) + { + // common nodes: + int pi1 = 0, pi2; + while (pi1 == i || pi1 == j) + pi1++; + pi2 = 6 - i - j - pi1; + /* + INDEX_2 i2(el.PNum(pi1+1), el.PNum(pi2+1)); + i2.Sort(); + if (!segmentht->Used (i2)) + */ + if (!segedge[pi1][pi2]) + { + // 2 boundary faces withoud edge in between + // cout << "p1, p2 = " << pi1 << "," << pi2 << endl; + // cout << "tet illegal due to first case" << endl; + el.SetLegal (0); + return 0; + } + } + } + + + // three boundary edges meeting in a Surface point + for (i = 1; i <= 4; i++) + { + int alledges = 1; + if (PointType(el.PNum(i)) == SURFACEPOINT) + { + for (j = 1; j <= 4; j++) + if (j != i) + { + /* + INDEX_2 i2(el.PNum(i), el.PNum(j)); + i2.Sort(); + if (!boundaryedges->Used(i2)) + */ + if (!bedge[i-1][j-1]) + { + alledges = 0; + break; + } + } + if (alledges) + { + // cout << "tet illegal due to unmarked node" << endl; + el.SetLegal (0); + return 0; + } + } + } + + + /* + { + // having 3 boundary edges and 4 surface nodes ??? + int nodehasedge[4]; + int canbe = 1; // can be that illegal tet + + for (i = 0; i < 4; i++) + nodehasedge[i] = 0; + for (i = 1; i <= 4; i++) + { + if (PointType(el.PNum(i)) != SURFACEPOINT) + canbe = 0; + for (j = i+1; j <= 4; j++) + { + INDEX_2 i2(el.PNum(i), el.PNum(j)); + i2.Sort(); + if (boundaryedges->Used(i2)) + { + nodehasedge[i-1] = 1; + nodehasedge[j-1] = 1; + } + + } + } + for (i = 0; i < 4; i++) + if (!nodehasedge[i]) + canbe = 0; + + if (canbe) return 0; + + } + */ + + { + // two connected edges on surface, but no face + + int ltestmode = 0; // (el.PNum(1) == 10516); + + if (ltestmode) + { + (*testout) << "pnums: " << endl; + for (i = 1; i <= 4; i++) + (*testout) << el.PNum(i) << " "; + (*testout) << endl; + } + + for (i = 1; i <= 4; i++) + if (PointType(el.PNum(i)) == SURFACEPOINT) + for (j = 1; j <= 4; j++) + if (j != i) + for (k = j+1; k <= 4; k++) + if (k != i) + { + int fnr = 10 - i - j - k; + + if (!bface[fnr-1] && + bedge[i-1][j-1] && + bedge[i-1][k-1]) + { + el.SetLegal (0); + return 0; + } + /* + INDEX_2 e1(el.PNum(i), el.PNum(j)); + e1.Sort(); + INDEX_2 e2(el.PNum(i), el.PNum(k)); + e2.Sort(); + INDEX_3 face(el.PNum(i), el.PNum(j), el.PNum(k)); + face.Sort(); + + if (ltestmode) + { + (*testout) << "i, j, k = " << i << ", " << j << ", " << k << endl; + (*testout) << "eij = " << boundaryedges->Used(e1) + << " eik = " << boundaryedges->Used(e2) + << " face = " << surfelementht->Used (face) << endl; + + } + + if (boundaryedges->Used(e1) && + boundaryedges->Used(e2) && + !surfelementht->Used (face)) + { + // cout << "tet illegal due to last case" << endl; + el.SetLegal (0); + return 0; + } + */ + } + + } + + + { + // connected surface edge and edge edge, but no face + + for (i = 1; i <= 4; i++) + if (PointType(el.PNum(i)) == EDGEPOINT) + for (j = 1; j <= 4; j++) + if (j != i) + for (k = j+1; k <= 4; k++) + if (k != i) + { + int fnr = 10 - i - j - k; + + if (!bface[fnr-1] && + (bedge[i-1][j-1] && segedge[i-1][k-1] || + segedge[i-1][j-1] && bedge[i-1][k-1])) + { + el.SetLegal (0); + return 0; + } + } + + } + + + + + + + el.SetLegal (1); + return 1; + + /* + int i1, i2, i3, i4, j; + if (PointType(el.PNum(1)) != INNERPOINT && + PointType(el.PNum(2)) != INNERPOINT && + PointType(el.PNum(3)) != INNERPOINT && + PointType(el.PNum(4)) != INNERPOINT) + { + for (i1 = 1; i1 <= surfacesonnode.EntrySize(el.PNum(1)); i1++) + for (i2 = 1; i2 <= surfacesonnode.EntrySize(el.PNum(2)); i2++) + if (surfacesonnode.Get(el.PNum(1), i1) == + surfacesonnode.Get(el.PNum(2), i2)) + for (i3 = 1; i3 <= surfacesonnode.EntrySize(el.PNum(3)); i3++) + if (surfacesonnode.Get(el.PNum(1), i1) == + surfacesonnode.Get(el.PNum(3), i3)) + for (i4 = 1; i4 <= surfacesonnode.EntrySize(el.PNum(4)); i4++) + if (surfacesonnode.Get(el.PNum(1), i1) == + surfacesonnode.Get(el.PNum(4), i4)) + { + int j, numbe = 0; + INDEX_2 i2; + + for (j = 1; j <= 6; j++) + { + switch (j) + { + case 1: + i2.I1() = el.PNum(1); + i2.I2() = el.PNum(2); break; + case 2: + i2.I1() = el.PNum(1); + i2.I2() = el.PNum(3); break; + case 3: + i2.I1() = el.PNum(1); + i2.I2() = el.PNum(4); break; + case 4: + i2.I1() = el.PNum(2); + i2.I2() = el.PNum(3); break; + case 5: + i2.I1() = el.PNum(2); + i2.I2() = el.PNum(4); break; + case 6: + i2.I1() = el.PNum(3); + i2.I2() = el.PNum(4); break; + } + + i2.Sort(); + if (boundaryedges->Used (i2)) numbe++; + } + + if (numbe >= 4) + { +// (*testout) +// << "Tet illegal: " +// << "mat = " << el.GetIndex() << " " +// << "surf = " << surfacesonnode.Get(el.PNum(1), i1) +// << " " +// << el.PNum(1) << " " +// << el.PNum(2) << " " +// << el.PNum(3) << " " +// << el.PNum(4) << endl; + + return 0; + } + } + } + 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() +{ + int oldne, oldnse; + int i, j, k, l; + + oldne = GetNE(); + for (i = 1; i <= oldne; i++) + { + Element el = VolumeElement(i); + if (el.GetType() == PRISM) + { + // (*testout) << "split el: " << el << " to "; + + // prism, to 3 tets + + // make minimal node to node 1 + int minpi=0; + PointIndex minpnum; + minpnum = GetNP() + 1; + + for (j = 1; j <= 6; j++) + { + if (el.PNum(j) < minpnum) + { + minpnum = el.PNum(j); + minpi = j; + } + } + + if (minpi >= 4) + { + for (j = 1; j <= 3; j++) + Swap (el.PNum(j), el.PNum(j+3)); + minpi -= 3; + } + + while (minpi > 1) + { + int hi = 0; + for (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, + */ + + (*testout) << " rot el = " << el << " "; + + 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 (j = 1; j <= 3; j++) + { + Element nel(4); + for (k = 1; k <= 4; k++) + nel.PNum(k) = el.PNum(min2pi[4 * j + k - 5]); + nel.SetIndex (el.GetIndex()); + + int legal = 1; + for (k = 1; k <= 3; k++) + for (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) (*testout) << "no legal"; + (*testout) << endl; + } + + + if (el.GetType() == PYRAMID) + { + // pyramid, to 2 tets + + + + 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.PNum(1), el.PNum(3)) < + min2 (el.PNum(2), el.PNum(4))) + min2pi = &ntets[0][0]; + else + min2pi = &ntets[1][0]; + + + int firsttet = 1; + for (j = 1; j <= 2; j++) + { + Element nel(4); + for (k = 1; k <= 4; k++) + nel.PNum(k) = el.PNum(min2pi[4 * j + k - 5]); + nel.SetIndex (el.GetIndex()); + + + int legal = 1; + for (k = 1; k <= 3; k++) + for (l = k+1; l <= 4; l++) + if (nel.PNum(k) == nel.PNum(l)) + legal = 0; + + if (legal) + { + (*testout) << nel << " "; + if (firsttet) + { + VolumeElement(i) = nel; + firsttet = 0; + } + else + { + AddVolumeElement(nel); + } + } + } + (*testout) << endl; + + + + + } + } + + + oldnse = GetNSE(); + for (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 (j = 0; j <6; j++) + (*testout) << min2pi[j] << " "; + + + int firsttri = 1; + for (j = 1; j <= 2; j++) + { + Element2d nel(3); + for (k = 1; k <= 3; k++) + nel.PNum(k) = el.PNum(min2pi[3 * j + k - 4]); + nel.SetIndex (el.GetIndex()); + + int legal = 1; + for (k = 1; k <= 2; k++) + for (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; + + } + } + + + for (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)); + } + timestamp = NextTimeStamp(); +} + +void Mesh :: BuildElementSearchTree () +{ + if (elementsearchtreets == GetTimeStamp()) + return; + + NgLock lock(mutex); + lock.Lock(); + + PrintMessage (4, "Rebuild element searchtree"); + + if (elementsearchtree) + delete elementsearchtree; + elementsearchtree = NULL; + + Box3d box; + int i, j; + int ne = GetNE(); + if (!ne) + { + lock.UnLock(); + return; + } + + box.SetPoint (Point (VolumeElement(1).PNum(1))); + for (i = 1; i <= ne; i++) + { + const Element & el = VolumeElement(i); + for (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 (i = 1; i <= ne; i++) + { + const Element & el = VolumeElement(i); + box.SetPoint (Point (el.PNum(1))); + for (j = 1; j <= el.GetNP(); j++) + box.AddPoint (Point (el.PNum(j))); + + elementsearchtree -> Insert (box.PMin(), box.PMax(), i); + } + + elementsearchtreets = GetTimeStamp(); + + lock.UnLock(); +} + + +int Mesh :: GetElementOfPoint (const Point3d & p, + double lami[3]) const +{ + if (dimension == 2) + { + int i, j; + Vec3d col1, col2, col3; + Vec3d rhs, sol; + double eps = 1e-6; + int ne; + + ARRAY<int> locels; + if (0) + { + elementsearchtree->GetIntersecting (p, p, locels); + ne = locels.Size(); + } + else + ne = GetNSE(); + + ARRAY<Element2d> loctrigs; + Vec3d nv(0, 0, 1); + + for (i = 1; i <= ne; i++) + { + int ii; + if (0) + ii = locels.Get(i); + else + ii = i; + + // SurfaceElement(ii).GetTets (loctets); + loctrigs.SetSize(1); + loctrigs.Elem(1) = SurfaceElement(ii); + + for (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 = nv; + rhs = p - p1; + + SolveLinearSystem (col1, col2, col3, rhs, sol); + + if (sol.X() >= -eps && sol.Y() >= -eps && + sol.X() + sol.Y() <= 1+eps) + { + lami[0] = sol.X(); + lami[1] = sol.Y(); + lami[2] = sol.Z(); + return ii; + } + } + } + + return 0; + } + + else + + { + int i, j; + Vec3d col1, col2, col3; + Vec3d rhs, sol; + double eps = 1e-4; + int ne; + + ARRAY<int> locels; + if (elementsearchtree) + { + // update if necessary: + const_cast<Mesh&>(*this).BuildElementSearchTree (); + elementsearchtree->GetIntersecting (p, p, locels); + ne = locels.Size(); + } + else + ne = GetNE(); + + ARRAY<Element> loctets; + for (i = 1; i <= ne; i++) + { + int ii; + if (elementsearchtree) + ii = locels.Get(i); + else + ii = i; + + VolumeElement(ii).GetTets (loctets); + + for (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<Point3d> pointsloc; + + VolumeElement(ii).GetTetsLocal (loctetsloc); + VolumeElement(ii).GetNodesLocalNew (pointsloc); + + const Element & le = loctetsloc.Get(j); + + Point3d p = + 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] = p.X(); + lami[1] = p.Y(); + lami[2] = p.Z(); + return ii; + } + } + } + + 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 () +{ + int fdi; + int i, j; + int np = GetNP(); + + BitArray usedp(np); + + fdi = 1; + while (fdi <= GetNFD()) + { + int firstel = 0; + for (i = 1; i <= GetNSE(); i++) + if (SurfaceElement(i).GetIndex() == fdi) + { + firstel = i; + break; + } + if (!firstel) continue; + + usedp.Clear(); + for (j = 1; j <= SurfaceElement(firstel).GetNP(); j++) + usedp.Set (SurfaceElement(firstel).PNum(j)); + + int changed; + do + { + changed = 0; + for (i = 1; i <= GetNSE(); i++) + { + const Element2d & el = SurfaceElement(i); + if (el.GetIndex() != fdi) + continue; + + int has = 0; + int hasno = 0; + for (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 (j = 1; j <= el.GetNP(); j++) + usedp.Set (el.PNum(j)); + } + } + while (changed); + + int nface = 0; + for (i = 1; i <= GetNSE(); i++) + { + Element2d & el = SurfaceElement(i); + if (el.GetIndex() != fdi) + continue; + + int hasno = 0; + for (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 :: GetSurfaceElementsOfFace (int facenr, ARRAY<SurfaceElementIndex> & sei) const +{ + sei.SetSize (0); + for (SurfaceElementIndex i = 0; i < GetNSE(); i++) + if ( (*this)[i].GetIndex () == facenr && (*this)[i][0] >= PointIndex::BASE ) + sei.Append (i); +} + + + + +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 :: 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; + } +} + + +/* +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; + + int i; + for (i = 1; i <= GetNSE(); i++) + if (SurfaceElement(i).GetIndex() == faceindex && + SurfaceElement(i).GetNP() != 3) + return 0; + return 1; +} + +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 :: 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/Netgen/libsrc/meshing/meshclass.hpp b/Netgen/libsrc/meshing/meshclass.hpp new file mode 100644 index 0000000000..4c03a36e14 --- /dev/null +++ b/Netgen/libsrc/meshing/meshclass.hpp @@ -0,0 +1,591 @@ +#ifndef MESHCLASS +#define MESHCLASS + +/**************************************************************************/ +/* File: meshclass.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Nov. 99 */ +/**************************************************************************/ + +/* + The mesh class +*/ + + + +enum resthtype { RESTRICTH_FACE, RESTRICTH_EDGE, + RESTRICTH_SURFACEELEMENT, RESTRICTH_POINT, RESTRICTH_SEGMENT }; + +/// 2d/3d mesh +class Mesh +{ +public: + // typedef MoveableArray<MeshPoint> 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; + /// type of point, is set in calcsurfacesofnode + ARRAY<POINTTYPE,PointIndex::BASE> ptyps; + /// type of element, set in calcsurfacesofnode + ARRAY<ELEMENTTYPE> eltyps; + + /// 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_HASHTABLE<int> * segmentht; + /// + INDEX_3_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; + /// + ARRAY<double> maxhdomain; + + /** + the face-index of the surface element maps into + this table. + */ + ARRAY<FaceDescriptor> facedecoding; + + /// sub-domain materials + ARRAY<char*> materials; + + /// 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 semaphor. + NgMutex mutex; + + +public: + + + /// 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; + + + + /// + Mesh(); + /// + ~Mesh(); + + /// + void DeleteMesh(); + + /// + void ClearSurfaceElements() + { + surfelements.SetSize(0); + timestamp = NextTimeStamp(); + } + + /// + void ClearVolumeElements() + { + volelements.SetSize(0); + eltyps.SetSize(0); + timestamp = NextTimeStamp(); + } + + /// + void ClearSegments() + { + segments.SetSize(0); + timestamp = NextTimeStamp(); + } + + /// + bool TestOk () const; + + + PointIndex AddPoint (const Point3d & p, int layer = 1); + 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]; } + + POINTTYPE PointType (int i) const { return ptyps.Get(i); } + POINTTYPE PointType (PointIndex pi) const { return ptyps[pi]; } + + const T_POINTS & Points() const { return points; } + T_POINTS & Points() { return points; } + ARRAY<POINTTYPE,PointIndex::BASE> & PointTypes() { return ptyps; } + + + + + + + SegmentIndex AddSegment (const Segment & s); + void DeleteSegment (int segnr) + { + segments.Elem(segnr).p1 = PointIndex::BASE-1; + segments.Elem(segnr).p2 = PointIndex::BASE-1; + } + + int GetNSeg () const { return segments.Size(); } + Segment & LineSegment(int i) { return segments.Elem(i); } + const Segment & LineSegment(int i) const { return segments.Get(i); } + + const Segment & operator[] (SegmentIndex si) const + { return segments[si]; } + Segment & operator[] (SegmentIndex si) + { return segments[si]; } + + + + + 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]; } + + + void GetSurfaceElementsOfFace (int facenr, ARRAY<SurfaceElementIndex> & sei) const; + + + + 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 (int i) const { return eltyps.Get(i); } + ELEMENTTYPE ElementType (ElementIndex i) const { return eltyps[i]; } + + const T_VOLELEMENTS & VolumeElements() const { return volelements; } + T_VOLELEMENTS & VolumeElements() { return volelements; } + + + /// + double ElementError (int eli) const; + + /// + 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 */ + void FindOpenElements (int dom = 0); + + + /** + finds segments without surface element, + and surface elements without neighbours. + store in opensegmentsy + */ + void FindOpenSegments (int surfnr = 0); + /** + remove one layer of surface elements + */ + void RemoveOneLayerSurfaceElements (); + + + int GetNOpenSegments () { return opensegments.Size(); } + const Segment & GetOpenSegment (int nr) { return opensegments.Get(nr); } + + /** + Checks overlap of boundary + return == 1, iff overlap + */ + int CheckOverlappingBoundary (); + /** + Checks consistent boundary + return == 0, everything ok + */ + int CheckConsistentBoundary () const; + + /* + checks element orientation + */ + int CheckVolumeMesh () const; + + + /** + finds average h of surface surfnr if surfnr > 0, + else of all surfaces. + */ + double AverageH (int surfnr = 0) const; + /// Calculates localh + void CalcLocalH (); + /// + void SetLocalH (const Point3d & pmin, const Point3d & pmax, double grading); + /// + void RestrictLocalH (const Point3d & p, double hloc); + /// + void RestrictLocalHLine (const Point3d & p1, const Point3d & p2, + double hloc); + /// number of elements per radius + void CalcLocalHFromSurfaceCurvature(double elperr); + /// + void RestrictLocalH (resthtype rht, int nr, double loch); + /// + void LoadLocalMeshSize (istream & ist); + /// + void SetGlobalH (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; } + + /// Find bounding box + void GetBox (Point3d & pmin, Point3d & pmax, int dom = -1) const; + + /// Find bounding box of points of typ ptyp or less + 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 + int 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 + { + 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); + } + + /** + Remove unused points. etc. + */ + void Compress (); + + /// + void Save (const char * filename) const; + /// + void Load (const char * filename); + + + /// + void ImproveMesh (OPTIMIZEGOAL goal = OPT_QUALITY); + + /// + void ImproveMeshJacobian (OPTIMIZEGOAL goal = OPT_QUALITY); + + + /* +#ifdef SOLIDGEOM + /// old + void ImproveMesh (const CSGeometry & surfaces, + OPTIMIZEGOAL goal = OPT_QUALITY); +#endif + */ + + /** + 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 + void BuildElementSearchTree (); + /// gives element of point, barycentric coordinates + int GetElementOfPoint (const Point3d & p, + double * lami) 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); } + + + /// + void SetMaterial (int domnr, const char * mat); + /// + const char * GetMaterial (int domnr) const; + + + /// + void ClearFaceDescriptors() + { facedecoding.SetSize(0); } + + /// + int GetNFD () const + { return facedecoding.Size(); } + + const FaceDescriptor & GetFaceDescriptor (int i) const + { return facedecoding.Get(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; } + + + + /// 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; } + + /// + friend void OptimizeRestart (Mesh & mesh3d); + /// + void PrintMemInfo (ostream & ost) const; + /// + friend class Meshing3; +}; + + + + +#endif diff --git a/Netgen/libsrc/meshing/meshfunc.cpp b/Netgen/libsrc/meshing/meshfunc.cpp new file mode 100644 index 0000000000..a3459ae71f --- /dev/null +++ b/Netgen/libsrc/meshing/meshfunc.cpp @@ -0,0 +1,745 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + 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 i, k, oldne; + PointIndex pi; + + int meshed; + int cntsteps; + + + // PlotStatistics3d * pstat; + // pstat = new TerminalPlotStatistics3d; + + + ARRAY<INDEX_2> connectednodes; + + mesh3d.Compress(); + + // mesh3d.PrintMemInfo (cout); + + int nonconsist = 0; + for (k = 1; k <= mesh3d.GetNDomains(); k++) + { + PrintMessage (3, "Check subdomain ", k, " / ", mesh3d.GetNDomains()); + + mesh3d.FindOpenElements(k); + + int res = 0; // mesh3d.CheckOverlappingBoundary(); + if (res) + { + PrintError ("Surface is overlapping !!"); + nonconsist = 1; + } + + res = mesh3d.CheckConsistentBoundary(); + 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 (k = 1; k <= mesh3d.GetNDomains(); k++) + { + if (multithread.terminate) + break; + + PrintMessage (2, ""); + PrintMessage (1, "Meshing subdomain ", k, " of ", mesh3d.GetNDomains()); + + mp.maxh = min2 (globmaxh, mesh3d.MaxHDomain(k)); + + mesh3d.CalcSurfacesOfNode(); + mesh3d.FindOpenElements(k); + + /* + if (mesh3d.CheckOverlappingBoundary()) + { + (*mycout) << "overlapping" << endl; + (*testout) << "overlapping !!!" << endl; + continue; + } + if (mesh3d.CheckConsistentBoundary()) + { + (*mycout) << "boundary not consistent" << endl; + (*testout) << "boundary not consistent !!!" << endl; + continue; + } + */ + + if (!mesh3d.GetNOpenElements()) + continue; + + int qstep; + for (qstep = 1; qstep <= 3; qstep++) + { + if (mesh3d.HasOpenQuads()) + { + string rulefile = ngdir; + /* + char rulefile[255]; + strcpy (rulefile, ngdir); + */ + const char ** rulep = NULL; + switch (qstep) + { + case 1: + // strcat (rulefile, "/rules/prisms2.rls"); + rulefile += "/rules/prisms2.rls"; + rulep = prismrules2; + break; + case 2: // connect pyramid to triangle + // strcat (rulefile, "/rules/pyramids2.rls"); + rulefile += "/rules/pyramids2.rls"; + rulep = pyramidrules2; + break; + case 3: // connect to vis-a-vis point + // strcat (rulefile, "/rules/pyramids.rls"); + rulefile += "/rules/pyramids.rls"; + rulep = pyramidrules; + break; + } + + // Meshing3 meshing(rulefile.c_str(), pstat); + Meshing3 meshing(NULL, rulep); + + MeshingParameters mpquad = mp; + + mpquad.giveuptol = 15; + mpquad.baseelnp = 4; + mpquad.starshapeclass = 100; + + for (pi = PointIndex::BASE; + pi < mesh3d.GetNP()+PointIndex::BASE; pi++) + meshing.AddPoint (mesh3d[pi], pi); + + mesh3d.GetIdentifications().GetPairs (0, connectednodes); + for (i = 1; i <= connectednodes.Size(); i++) + meshing.AddConnectedPair (connectednodes.Get(i)); + + for (i = 1; i <= mesh3d.GetNOpenElements(); i++) + { + Element2d hel = mesh3d.OpenElement(i); + meshing.AddBoundaryElement (hel); + } + + oldne = mesh3d.GetNE(); + + meshing.GenerateMesh (mesh3d, mpquad); + + for (i = oldne + 1; i <= mesh3d.GetNE(); i++) + mesh3d.VolumeElement(i).SetIndex (k); + + (*testout) + << "mesh has " << mesh3d.GetNE() << " prism ? 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(NULL); + + mesh3d.FindOpenElements(k); + + + for (pi = PointIndex::BASE; + pi < mesh3d.GetNP()+PointIndex::BASE; pi++) + meshing.AddPoint (mesh3d[pi], pi); + + + for (i = 1; i <= mesh3d.GetNOpenElements(); i++) + 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); + } + */ + + + // mp.blockfill = globflags.GetDefineFlag ("blockfill"); + meshing.Delaunay (mesh3d, mp); + // return MESHING3_OK; + + for (i = oldne + 1; i <= mesh3d.GetNE(); i++) + mesh3d.VolumeElement(i).SetIndex (k); + + PrintMessage (3, mesh3d.GetNP(), " points, ", + mesh3d.GetNE(), " elements"); + } + + + cntsteps = 0; + do + { + if (multithread.terminate) + break; + + // mesh3d.CalcSurfacesOfNode(); + mesh3d.FindOpenElements(k); + PrintMessage (5, mesh3d.GetNOpenElements(), " open faces"); + cntsteps++; + if (cntsteps > mp.maxoutersteps) + throw NgException ("Stop meshing since too many attempts"); + // return MESHING3_OUTERSTEPSEXCEEDED; + + /* + if (mesh3d.CheckOverlappingBoundary()) + { + (*mycout) << "overlapping" << endl; + (*testout) << "overlapping !!!!" << endl; + break; + } + if (mesh3d.CheckConsistentBoundary()) + { + (*mycout) << "boundary not consistent" << endl; + (*testout) << "boundary not consistent !!!" << endl; + // break; + } + */ + + + /* + char rulefile[255]; + strcpy (rulefile, ngdir); + strcat (rulefile, "/tetra.rls"); + */ + string rulefile = ngdir + "/tetra.rls"; + PrintMessage (1, "start tetmeshing"); + + // Meshing3 meshing(rulefile, pstat); + Meshing3 meshing(NULL); + +#ifdef MYGRAPH + Point3d pmin, pmax; + mesh3d.GetBox (pmin, pmax, k); + rot.SetCenter (Center (pmin, pmax)); +#endif + + for (i = 1; i <= mesh3d.GetNP(); i++) + meshing.AddPoint (mesh3d.Point(i), i); + + for (i = 1; i <= mesh3d.GetNOpenElements(); i++) + meshing.AddBoundaryElement (mesh3d.OpenElement(i)); + + + oldne = mesh3d.GetNE(); + + mp.giveuptol = 15; // int(globflags.GetNumFlag ("giveuptol", 15)); + mp.sloppy = 5; + meshing.GenerateMesh (mesh3d, mp); + + for (i = oldne + 1; i <= mesh3d.GetNE(); i++) + mesh3d.VolumeElement(i).SetIndex (k); + + + mesh3d.CalcSurfacesOfNode(); + mesh3d.FindOpenElements(k); + + teterrpow = 2; + if (mesh3d.GetNOpenElements() != 0) + { + meshed = 0; + PrintMessage (5, mesh3d.GetNOpenElements(), " open faces found"); + + // mesh3d.Save ("tmp.vol"); + + + MeshOptimize3d optmesh; + + const char * optstr = "mcmstmcmstmcmstmcm"; + int j; + for (j = 1; j <= strlen(optstr); j++) + { + mesh3d.CalcSurfacesOfNode(); + mesh3d.FreeOpenElementsEnvironment(2); + + 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(OPT_REST); break; + } + + } + + mesh3d.FindOpenElements(k); + PrintMessage (3, "Call remove problem"); + RemoveProblem (mesh3d); + mesh3d.FindOpenElements(k); + } + else + { + meshed = 1; + PrintMessage (1, "Success !"); + } + } + while (!meshed); + + PrintMessage (1, mesh3d.GetNP(), " points, ", + mesh3d.GetNE(), " elements"); + } + + mp.maxh = globmaxh; + + MeshQuality3d (mesh3d); + + // delete pstat; + + 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, j; + + 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; + + teterrpow = mp.opterrpow; + for (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 't': optmesh.SwapImprove2(mesh3d); break; +#ifdef SOLIDGEOM + case 'm': mesh3d.ImproveMesh(*geometry); break; + case 'M': mesh3d.ImproveMesh(*geometry); break; +#else + case 'm': mesh3d.ImproveMesh(); break; + case 'M': mesh3d.ImproveMesh(); break; +#endif + + case 'j': mesh3d.ImproveMeshJacobian(); break; + } + } + MeshQuality3d (mesh3d); + } + + return MESHING3_OK; + } + + + + + void RemoveIllegalElements (Mesh & mesh3d) + { + int it = 10; + int nillegal, oldn; + int i; + + PrintMessage (1, "Remove Illegal Elements"); + // return, if non-pure tet-mesh + /* + if (!mesh3d.PureTetMesh()) + return; + */ + mesh3d.CalcSurfacesOfNode(); + + nillegal = mesh3d.MarkIllegalElements(); + + MeshOptimize3d optmesh; + 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/Netgen/libsrc/meshing/meshfunc.hpp b/Netgen/libsrc/meshing/meshfunc.hpp new file mode 100644 index 0000000000..0e530ed2f0 --- /dev/null +++ b/Netgen/libsrc/meshing/meshfunc.hpp @@ -0,0 +1,42 @@ +#ifndef FILE_MESHFUNC +#define FILE_MESHFUNC + +/**************************************************************************/ +/* File: meshfunc.hh */ +/* Author: Johannes Gerstmayr */ +/* Date: 26. Jan. 98 */ +/**************************************************************************/ + + +/* + Functions for mesh-generations strategies + */ + +class Mesh; +class MeshingParameters3; +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/Netgen/libsrc/meshing/meshfunc2d.cpp b/Netgen/libsrc/meshing/meshfunc2d.cpp new file mode 100644 index 0000000000..f329d1df76 --- /dev/null +++ b/Netgen/libsrc/meshing/meshfunc2d.cpp @@ -0,0 +1,61 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + + void Optimize2d (Mesh & mesh, MeshingParameters & mp) + { + int i, j; + + 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 (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); + 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/Netgen/libsrc/meshing/meshing.hpp b/Netgen/libsrc/meshing/meshing.hpp new file mode 100644 index 0000000000..3a60f1f7c1 --- /dev/null +++ b/Netgen/libsrc/meshing/meshing.hpp @@ -0,0 +1,48 @@ +#ifndef FILE_MESHING +#define FILE_MESHING + +#include <myadt.hpp> +#include <gprim.hpp> +#include <linalg.hpp> +#include <opti.hpp> + +namespace netgen +{ + + class CSGeometry; + + +#include "msghandler.hpp" + +#include "meshtype.hpp" +#include "localh.hpp" +#include "meshclass.hpp" +#include "global.hpp" + + +#include "meshtool.hpp" +#include "ruler2.hpp" +#include "adfront2.hpp" +#include "meshing2.hpp" +#include "improve2.hpp" + + +#include "geomsearch.hpp" +#include "adfront3.hpp" +#include "ruler3.hpp" +#include "meshing3.hpp" +#include "improve3.hpp" +#include "findip.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" +} + +#endif diff --git a/Netgen/libsrc/meshing/meshing2.cpp b/Netgen/libsrc/meshing/meshing2.cpp new file mode 100644 index 0000000000..efcb51346e --- /dev/null +++ b/Netgen/libsrc/meshing/meshing2.cpp @@ -0,0 +1,1650 @@ +#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; + // static const Meshing2 * meshthis; + + + + Meshing2 :: Meshing2 (const Box3d & aboundingbox) + { + boundingbox = aboundingbox; + + LoadRules (NULL); + // LoadRules ("quad.rls"); + // LoadRules ("triangle.rls"); + + adfront = new AdFront2(boundingbox); + starttime = GetTime(); + } + + + 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) + { + // (*testout) << "add point " << globind << endl; + adfront ->AddPoint (p, globind, mgi); + } + + 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, i2, 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; + } + + 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 (Point3d & p1, 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; + + 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, double gh, int facenr) + { + ARRAY<int> pindex, lindex; + ARRAY<int> delpoints, dellines; + + ARRAY<PointGeomInfo> upgeominfo; // unique info + ARRAY<MultiPointGeomInfo> mpgeominfo; // multiple info + + ARRAY<Element2d> locelements; + + int i, k, z1, z2, j, oldnp; + SurfaceElementIndex sei; + int baselineindex; + bool found; + int rulenr; + int globind; + Point3d p1, p2; + + const PointGeomInfo * blgeominfo1; + const PointGeomInfo * blgeominfo2; + + bool morerisc; + bool debugflag; + + double h, his, hshould; + + + // 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; + // meshthis = this; + + StartMesh(); + + ARRAY<Point2d> chartboundpoints; + ARRAY<Point3d> chartboundpoints3d; + ARRAY<INDEX_2> chartboundlines; + + // illegal points: points with more then 50 elements per node + int maxlegalpoint, maxlegalline; + 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) + { + const Point3d & sep1 = mesh[sel.PNum(1)]; + const Point3d & sep2 = mesh[sel.PNum(2)]; + const Point3d & sep3 = mesh[sel.PNum(3)]; + Point3d sepmin(sep1), sepmax(sep2); + sepmin.SetToMin (sep2); + sepmin.SetToMin (sep3); + sepmin.SetToMax (sep2); + sepmin.SetToMax (sep3); + + surfeltree.Insert (sepmin, sepmax, sei); + } + + + double trigarea = Cross (Vec3d (mesh.Point (sel.PNum(1)), + mesh.Point (sel.PNum(2))), + Vec3d (mesh.Point (sel.PNum(1)), + mesh.Point (sel.PNum(3)))).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; + + } + + + char * savetask = multithread.task; + multithread.task = "Surface meshing"; + + adfront ->SetStartFront (); + + + int plotnexttrial = 0; + // starttime = GetTime(); + while (!adfront ->Empty()) // && !multithread.terminate) + { + 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 + 1))); + plotnexttrial += 1000; + } + + + // unique-pgi, multi-pgi + upgeominfo.SetSize(0); + mpgeominfo.SetSize(0); + + + nfaces = adfront->GetNFL(); + trials ++; + + + if (trials % 1000 == 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) << "\n"; + } + + + baselineindex = adfront -> SelectBaseLine (p1, p2, blgeominfo1, blgeominfo2); + + // cout << "baseline = " << baselineindex << ", p1, p2 = " << p1 << ", " << p2 << endl; + + 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; + + + qualclass = + adfront ->GetLocals (baselineindex, locpoints, mpgeominfo, loclines, + pindex, lindex, 5 * max2(his, hshould)); + + + if (qualclass > 200) + { + PrintMessage (3, "give up with qualclass ", qualclass); + PrintMessage (3, "number of frontlines = ", adfront->GetNFL()); + 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; + } + + + // 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(); + + DefineTransformation (p1, p2, blgeominfo1, blgeominfo2); + + plainpoints.SetSize (locpoints.Size()); + plainzones.SetSize (locpoints.Size()); + + // (*testout) << endl; + + for (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)); + } + + 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 (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 (0); + 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 (i = 1; i <= legalpoints.Size(); i++) + legalpoints.Elem(i) = 1; + + + for (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) == 0) + 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 (mparam.checkchartboundary) + { + for (i = 1; i <= chartboundpoints.Size(); i++) + { + plainpoints.Append (chartboundpoints.Get(i)); + locpoints.Append (chartboundpoints3d.Get(i)); + legalpoints.Append (0); + } + + + for (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); + if (!rulenr) + { + found = 0; + if ( debugflag || debugparam.haltnosuccess ) + PrintWarning ("no rule found"); + } + } + + for (i = 1; i <= locelements.Size() && found; i++) + { + const Element2d & el = locelements.Get(i); + for (j = 1; j <= el.GetNP(); j++) + if (el.PNum(j) <= oldnp && !pindex.Get(el.PNum(j))) + { + found = 0; + PrintSysError ("meshing2, index missing"); + } + } + + + if (found) + { + locpoints.SetSize (plainpoints.Size()); + upgeominfo.SetSize(locpoints.Size()); + + for (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 (i = oldnl+1; i <= loclines.Size(); i++) + { + double eh = Dist (locpoints.Get(loclines.Get(i).I1()), + locpoints.Get(loclines.Get(i).I2())); + if (eh > newedgemaxh) + newedgemaxh = eh; + } + + for (i = 1; i <= locelements.Size(); i++) + { + Point3d pmin = locpoints.Get(locelements.Get(i).PNum(1)); + Point3d pmax = pmin; + for (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; + } + + // 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 (i = 1; i <= locelements.Size(); i++) + for (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 && mparam.checkoverlap) + { + // test for overlaps + + Point3d hullmin(1e10, 1e10, 1e10); + Point3d hullmax(-1e10, -1e10, -1e10); + + for (i = 1; i <= locelements.Size(); i++) + for (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 (i = oldnp+1; i <= locpoints.Size(); i++) + critpoints.Append (locpoints.Get(i)); + + for (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 (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++) + { + 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 (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 (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 (i = oldnp+1; i <= locpoints.Size(); i++) + { + globind = mesh.AddPoint (locpoints.Get(i)); + pindex.Elem(i) = adfront -> AddPoint (locpoints.Get(i), globind); + } + + for (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()) == 0 || + pindex.Get(loclines.Get(i).I2()) == 0) + { + (*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 (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 (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 (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; + + + + + const Point3d & sep1 = mesh.Point (mtri.PNum(1)); + const Point3d & sep2 = mesh.Point (mtri.PNum(2)); + const Point3d & sep3 = mesh.Point (mtri.PNum(3)); + + Point3d sepmin(sep1), sepmax(sep1); + for (j = 2; j <= mtri.GetNP(); j++) + { + sepmin.SetToMin (mesh.Point (mtri.PNum(j))); + sepmax.SetToMax (mesh.Point (mtri.PNum(j))); + } + + surfeltree.Insert (sepmin, sepmax, mesh.GetNSE()); + + + 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; + + + + + for (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 (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 (i = 1; i <= dellines.Size(); i++) + adfront -> DeleteLine (lindex.Get(dellines.Get(i))); + + // rname = rules[found]->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 ) + { + cout << "success" << 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())); + } + */ + + + glrender(1); + } + } + else + { + adfront -> IncrementClass (lindex.Get(1)); + + if ( debugparam.haltnosuccess || debugflag ) + { + cout << "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 (i = 1; i <= loclines.Size(); i++) + { + (*testout) << "line "; + for (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; + + + // cout << "surfeltree.depth = " << surfeltree.Tree().Depth() << endl; + EndMesh (); + + if (!adfront->Empty()) + return MESHING2_GIVEUP; + + return MESHING2_OK; + } + + + + + + + + + +} + + + + + + + +#ifdef OPENGL + +/* *********************** 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; + + // 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/Netgen/libsrc/meshing/meshing2.hpp b/Netgen/libsrc/meshing/meshing2.hpp new file mode 100644 index 0000000000..e827a5419b --- /dev/null +++ b/Netgen/libsrc/meshing/meshing2.hpp @@ -0,0 +1,149 @@ +#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; + /// + Box3d boundingbox; + /// + double starttime; +public: + /// + Meshing2 (const Box3d & aboundingbox); + + /// + virtual ~Meshing2 (); + + /// Load rules, either from file, or compiled rules + void LoadRules (const char * filename); + + /// + MESHING2_RESULT GenerateMesh (Mesh & mesh, double gh, int facenr); + + /// + void AddPoint (const Point3d & p, PointIndex globind, MultiPointGeomInfo * mgi = NULL); + + /// + void AddBoundaryElement (INDEX i1, INDEX i2, + const PointGeomInfo & gi1, const PointGeomInfo & gi2); + + /// + void SetStartTime (double astarttime); + +protected: + /// + virtual void StartMesh (); + /// + virtual void EndMesh (); + /// + virtual double CalcLocalH (const Point3d & p, double gh) const; + + /// + virtual void DefineTransformation (Point3d & p1, 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); + + +}; + + + + + + + + +#endif + + + + + + + diff --git a/Netgen/libsrc/meshing/meshing3.cpp b/Netgen/libsrc/meshing/meshing3.cpp new file mode 100644 index 0000000000..46b89b28cd --- /dev/null +++ b/Netgen/libsrc/meshing/meshing3.cpp @@ -0,0 +1,1303 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + +double minother; +double minwithoutother; + + + + + + + +/* +MeshingParameters3 :: MeshingParameters3() +{ + h = 1; + giveuptol = 10; + maxoutersteps = 5; + baseelnp = 0; + starshapeclass = 5; + blockfill = 0; + sloppy = 1; + optsteps = 2; + optstr = "cmsmdm"; +} +*/ + + + + + +MeshingStat3d :: MeshingStat3d () +{ + cntsucc = cnttrials = cntelem = qualclass = 0; + vol0 = h = 1; + problemindex = 1; +} + + + + + +Meshing3 :: Meshing3 (const char * rulefilename) //, const PlotStatistics3d * aplotstat) + // : plotstat(aplotstat) +{ + int i; + tolfak = 1; + + LoadRules (rulefilename, NULL); + adfront = new AdFront3; + + problems.SetSize (rules.Size()); + foundmap.SetSize (rules.Size()); + canuse.SetSize (rules.Size()); + ruleused.SetSize (rules.Size()); + + for (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 * rulefilename, const char ** rulep) + // const PlotStatistics3d * aplotstat) + // : plotstat(aplotstat) +{ + 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]; + } +} + + +#ifdef ABC +TerminalPlotStatistics3d :: TerminalPlotStatistics3d() +{ + oldne = -1; +} + +void TerminalPlotStatistics3d :: Plot (const MeshingStat3d & stat) const +{ + if (stat.cntelem == oldne) + return; + + ((int&)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; +} + +#endif + + +static double CalcLocH (const ARRAY<Point3d> & locpoints, + const ARRAY<Element2d> & 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; +} + + +int Meshing3 :: AddPoint (const Point3d & p, INDEX globind) +{ + return adfront -> AddPoint (p, globind); +} + +void Meshing3 :: AddBoundaryElement (const Element2d & elem) +{ + adfront -> AddFace(elem); +} + +int Meshing3 :: AddConnectedPair (const INDEX_2 & apair) +{ + return adfront -> AddConnectedPair (apair); +} + +MESHING3_RESULT Meshing3 :: +GenerateMesh (Mesh & mesh, const MeshingParameters & mp) +{ + ARRAY<Point3d> locpoints; // local points + ARRAY<Element2d> 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 + + int loktestmode = 0; + + int uselocalh = mparam.uselocalh; + + int giveuptol = mp.giveuptol; // + MeshingStat3d stat; // statistics + int plotstat_oldne = -1; + + + // for star-shaped domain meshing + ARRAY<MeshPoint> grouppoints; + ARRAY<Element2d> groupfaces; + ARRAY<PointIndex> grouppindex; + ARRAY<INDEX> groupfindex; + + + float minerr; + int hasfound; + double tetvol; + int giveup = 0; + + + ARRAY<Point3d> tempnewpoints; + ARRAY<Element2d> 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"); + /* + if (multithread.terminate) + break; + */ + if (giveup) + break; + + // 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); // connecgted 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 Element2d & 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)); + + 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); + + stat.qualclass = + adfront -> GetLocals (baseelem, locpoints, locfaces, + pindex, findex, connectedpairs, + houter, hinner, + locfacesplit); + + + int pi1 = pindex.Get(locfaces.Elem(1).PNum(1)); + int pi2 = pindex.Get(locfaces.Elem(1).PNum(2)); + int pi3 = pindex.Get(locfaces.Elem(1).PNum(3)); + + /* + (*testout) << "baseel = " << baseelem << ", ind = " << findex.Get(1) << endl; + (*testout) << "pi = " << pi1 << ", " << pi2 << ", " << pi3 << endl; + */ + + loktestmode = 0; + /* + // 1085, 1084, 1491 + if ( (pi1 == 1085 || pi1 == 1084 || pi1 == 1491) && + (pi2 == 1085 || pi2 == 1084 || pi2 == 1491) && + (pi3 == 1085 || pi3 == 1084 || pi3 == 1491) ) + // if (findex.Get(1) == 7551) + { + (*testout) << "baseel = " << findex.Get(1) << ", points: "; + for (i = 1; i <= pindex.Size(); i++) + (*testout) << pindex.Get(i) << " "; + (*testout) << endl; + loktestmode = 1; + } + */ + // testmode = loktestmode; + + // cout << "baseelem = " << baseelem << " qualclass = " << stat.qualclass << 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; + } + else + for (i = 1; i <= allowpoint.Size(); i++) + allowpoint.Elem(i) = 1; + + + + if (stat.qualclass >= mp.starshapeclass) + { + // star-shaped domain removing + + grouppoints.SetSize (0); + groupfaces.SetSize (0); + grouppindex.SetSize (0); + groupfindex.SetSize (0); + + adfront -> GetGroup (findex.Get(1), grouppoints, groupfaces, + grouppindex, groupfindex); + + int onlytri = 1; + for (i = 1; i <= groupfaces.Size(); i++) + if (groupfaces.Get(i).GetNP() != 3) + onlytri = 0; + + if (onlytri && groupfaces.Size() <= 20 && + 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; + + for (rotind = 1; rotind <= locfaces.Get(1).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); + + 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; + } + + found = ApplyRules (plainpoints, allowpoint, + locfaces, locfacesplit, connectedpairs, + locelements, delfaces, + stat.qualclass, mp.sloppy, rotind, err); + + if (loktestmode) + { + (*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)++; + + + if (stat.qualclass > 80) + { + cerr << "Sorry, I failed" << endl; + mesh.Save ("tempvol.out"); + exit (1); + } + + + // 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) << "testmode found" << 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 (testmode) + { + (*testout) << "testmode locpoints" << 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)); + } + + locelements.SetSize (0); + delpoints.SetSize(0); + delfaces.SetSize(0); + + if (stat.qualclass >= giveuptol) + giveup = 1; +#ifdef MYGRAPH + if (plotvolmesh && plotvolmesh->GiveUp()) + giveup = 1; +#endif + } + + + + 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, i1, i2, i3, j1, j2, j3; + int n1, n2, n3, n, min1, min2, min3, max1, max2, max3; + int changed, filled; + double xmin, xmax, ymin, ymax, zmin, zmax; + 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 Element2d & 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, pi2, pi3, pi4; + + 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) + { + Element2d 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) +{ + int i, j; + + double filldist = mp.filldist; + + (*testout) << "blockfill local h" << endl; + (*testout) << "rel filldist = " << filldist << endl; + PrintMessage (3, "blockfill local h"); + + /* + (*mycout) << "boxes: " << mesh.LocalHFunction().GetNBoxes() << endl + << "filldist = " << filldist << endl; + */ + ARRAY<Point3d> npoints; + + adfront -> CreateTrees(); + + Point3d mpmin, mpmax; + // mesh.GetBox (mpmin, mpmax); + bool firstp = 1; + + double maxh = 0; + for (i = 1; i <= adfront->GetNF(); i++) + { + const Element2d & el = adfront->GetFace(i); + for (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; + + if (firstp) + { + mpmin = p1; + mpmax = p1; + firstp = 0; + } + else + { + mpmin.SetToMin (p1); + mpmax.SetToMax (p1); + } + } + } + + 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; + + int changed; + do + { + mesh.LocalHFunction().ClearFlags(); + + for (i = 1; i <= adfront->GetNF(); i++) + { + const Element2d & el = adfront->GetFace(i); + Point3d pmin = adfront->GetPoint (el.PNum(1)); + Point3d pmax = pmin; + + for (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); + // (*testout) << "cut : " << pmin << " - " << pmax << endl; + mesh.LocalHFunction().CutBoundary (pmin, pmax); + } + + locadfront = adfront; + mesh.LocalHFunction().FindInnerBoxes (adfront, NULL); + + npoints.SetSize(0); + mesh.LocalHFunction().GetInnerPoints (npoints); + + changed = 0; + for (i = 1; i <= npoints.Size(); i++) + { + if (mesh.LocalHFunction().GetH(npoints.Get(i)) > 1.5 * maxh) + { + mesh.LocalHFunction().SetH (npoints.Get(i), +maxh); + changed = 1; + } + } + } + while (changed); + + if (debugparam.slowchecks) + (*testout) << "Blockfill with points: " << endl; + for (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 (i = 1; i <= adfront->GetNF(); i++) + { + const Element2d & el = adfront->GetFace(i); + Point3d pmin = adfront->GetPoint (el.PNum(1)); + Point3d pmax = pmin; + + for (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 (i = 1; i <= adfront->GetNF(); i++) + { + const Element2d & el = adfront->GetFace(i); + Point3d pmin = adfront->GetPoint (el.PNum(1)); + Point3d pmax = pmin; + + for (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); + } + + locadfront = adfront; + loch2.FindInnerBoxes (adfront, NULL); + + npoints.SetSize(0); + loch2.GetOuterPoints (npoints); + + for (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/Netgen/libsrc/meshing/meshing3.hpp b/Netgen/libsrc/meshing/meshing3.hpp new file mode 100644 index 0000000000..e6829554fa --- /dev/null +++ b/Netgen/libsrc/meshing/meshing3.hpp @@ -0,0 +1,192 @@ +#ifndef FILE_MESHING3 +#define FILE_MESHING3 + + + + +// class PlotStatistics3d; + + +/* +/// +class MeshingParameters3 +{ +public: + /// global h + double h; + + /// give up quality class + int giveuptol; + + /// maximal outer steps + int maxoutersteps; + + /// if non-zero, baseelement must have baseelnp points + int baseelnp; + + /// class starting star-shape filling + int starshapeclass; + + /// call blockfill function + int blockfill; + + /// quality tolerances are handled less careful + double sloppy; + + /// number of optimizationsteps + int optsteps; + + /// + char * optstr; + + /// + MeshingParameters3(); +}; +*/ + + +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 char * rulefilename); + /// + Meshing3 (const char * rulefilename, 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<Element2d> & lfaces, INDEX lfacesplit, + INDEX_2_HASHTABLE<int> & connectedpairs, + ARRAY<Element> & elements, + ARRAY<INDEX> & delfaces, int tolerance, + double sloppy, int rotind1, + float & retminerr); + + /// + int AddPoint (const Point3d & p, INDEX globind); + /// + void AddBoundaryElement (const Element2d & 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, 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; +}; + + +/* +/// +class PlotStatistics3d +{ +public: + /// + PlotStatistics3d () { } + /// + virtual void Plot (const MeshingStat3d & stat) const = 0; +}; + + +/// +class TerminalPlotStatistics3d : public PlotStatistics3d +{ + int oldne; +public: + /// + TerminalPlotStatistics3d (); + /// + virtual void Plot (const MeshingStat3d & stat) const; +}; +*/ + + + +/* +template <typename POINTARRAY, typename FACEARRAY> +extern int FindInnerPoint (POINTARRAY & grouppoints, + FACEARRAY & groupfaces, + Point3d & p); + +*/ + + + + + +#endif + + + + + + + + + + diff --git a/Netgen/libsrc/meshing/meshtool.cpp b/Netgen/libsrc/meshing/meshtool.cpp new file mode 100644 index 0000000000..127d047820 --- /dev/null +++ b/Netgen/libsrc/meshing/meshtool.cpp @@ -0,0 +1,865 @@ +#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; + + std::cout<<"MeshTool"<<std::endl; + + 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 Point3d *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); + 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) +} + + + + + +double teterrpow = 2; + + +double CalcTetBadnessNew (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4, double h) +{ + 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) / 6; + + 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 = (lll) / (1832.82 * vol); // 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; + + return pow (err, teterrpow); +} + + + + + +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; + + 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).precision(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).X() << " " + << mesh.Point(i).Y() << " " + << mesh.Point(i).Z() << "\n"; + + of << 2 * mesh.GetNSeg() << endl; + for (i = 1; i <= mesh.GetNSeg(); i++) + { + seg = &mesh.LineSegment(i); + + of << seg->p2 << " " << seg->p1 << " " << 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).X() << " " + << mesh.Point(i).Y() << " " + << mesh.Point(i).Z() << 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).p1 << " " + << mesh2d.LineSegment(i).p2 << " " << 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).X() << " " + << mesh.Point(i).Y() << " " + << mesh.Point(i).Z() << 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 (ElementIndex 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 i, j, k; + + mesh.FindOpenElements(); + 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++) + { + 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/Netgen/libsrc/meshing/meshtool.hpp b/Netgen/libsrc/meshing/meshtool.hpp new file mode 100644 index 0000000000..397528876f --- /dev/null +++ b/Netgen/libsrc/meshing/meshtool.hpp @@ -0,0 +1,82 @@ +#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); +/// +extern double CalcTetBadnessGrad (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + const Point3d & p4, + double h, int pi, + Vec3d & grad); + + +/** 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); +#endif diff --git a/Netgen/libsrc/meshing/meshtype.cpp b/Netgen/libsrc/meshing/meshtype.cpp new file mode 100644 index 0000000000..7a8bcb513c --- /dev/null +++ b/Netgen/libsrc/meshing/meshtype.cpp @@ -0,0 +1,1880 @@ +#include <mystdlib.h> + +#include "meshing.hpp" + + +namespace netgen +{ + + MultiPointGeomInfo :: MultiPointGeomInfo() + { + cnt = 0; + } + + int MultiPointGeomInfo :: + AddPointGeomInfo (const PointGeomInfo & gi) + { + int k; + + for (k = 0; k < cnt; k++) + if (mgi[k].trignum == gi.trignum) + return 0; + + if (cnt < MULTIPOINTGEOMINFO_MAX) + { + mgi[cnt] = gi; + cnt++; + return 0; + } + // #ifdef DEVELOP + cout << "Please Increase MPGI - Size" << endl; + // #endif + return 1; + } + + + void MultiPointGeomInfo :: + Init () + { + cnt = 0; + } + + void MultiPointGeomInfo :: + DeleteAll () + { + cnt = 0; + } + + + + + Segment :: Segment() + { + p1 = p2 = 0; + geominfo[0].trignum=0; + geominfo[1].trignum=0; + surfnr1 = surfnr2 = 0; + edgenr = 0; + + singedge = 0; + + epgeominfo[0].edgenr = 1; + epgeominfo[0].dist = 0; + epgeominfo[1].edgenr = 1; + epgeominfo[1].dist = 0; + + pmid = 0; + } + + ostream & operator<<(ostream & s, const Segment & seg) + { + s << seg.p1 << "(gi=" << seg.geominfo[0].trignum << ") - " + << seg.p2 << "(gi=" << seg.geominfo[1].trignum << ")"; + return s; + } + + Element2d :: Element2d (int anp) + { + int i; + for (i = 0; i < 6; i++) + { + pnum[i] = 0; + geominfo[i].trignum = 0; + } + np = anp; + index = 0; + badel = 0; + deleted = 0; + switch (np) + { + case 3: typ = TRIG; break; + case 4: typ = QUAD; break; + case 6: typ = TRIG6; break; + } + order = 1; + } + + + Element2d :: Element2d (ELEMENT_TYPE atyp) + { + int i; + for (i = 0; i < 6; i++) + { + pnum[i] = 0; + geominfo[i].trignum = 0; + } + + SetType (atyp); + + index = 0; + badel = 0; + deleted = 0; + order = 1; + } + + + + + 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 < 6; i++) + geominfo[i].trignum = 0; + index = 0; + badel = 0; + refflag = 1; + deleted = 0; + order = 1; +} + +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 < 6; i++) + geominfo[i].trignum = 0; + index = 0; + badel = 0; + refflag = 1; + deleted = 0; + order = 1; +} + + +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])); +} + +void Element2d :: Invert2() +{ + switch (typ) + { + case TRIG: + { + Swap (pnum[1], pnum[2]); + 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) + { + PointIndex pi1; + if (PNum(1) < PNum(2) && PNum(1) < PNum(3)) + return; + else + { + if (PNum(2) < PNum(3)) + { + pi1 = PNum(2); + PNum(2) = PNum(3); + PNum(3) = PNum(1); + PNum(1) = pi1; + } + else + { + pi1 = PNum(3); + PNum(3) = PNum(2); + PNum(2) = PNum(1); + PNum(1) = pi1; + } + } + } + else + { + int i; + int mini = 1; + for (i = 2; i <= GetNP(); i++) + if (PNum(i) < PNum(mini)) mini = i; + + Element2d hel = (*this); + for (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(); + static 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(); + + if (pmat.Width() != np || pmat.Height() != 2) + { + (*testout) << "GetTransofrmation: pmat doesn't fit" << endl; + return; + } + + ComputeIntegrationPointData (); + DenseMatrix * dshapep = 0; + 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.Elem(1) = 1 - p.X() - p.Y(); + shape.Elem(2) = p.X(); + shape.Elem(3) = p.Y(); + break; + case QUAD: + shape.Elem(1) = (1-p.X()) * (1-p.Y()); + shape.Elem(2) = p.X() * (1-p.Y()); + shape.Elem(3) = p.X() * p.Y(); + shape.Elem(4) = (1-p.X()) * p.Y(); + break; + default: + PrintSysError ("Element2d::GetShape, illegal type ", typ); + } +} + +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 :: +GetPointMatrix (const ARRAY<Point2d> & points, + DenseMatrix & pmat) const +{ + int i; + int np = GetNP(); + if (pmat.Width() != np || pmat.Height() != 2) + { + cerr << "Element::GetPointMatrix: sizes don't fit" << endl; + return; + } + + for (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(); + static DenseMatrix trans(2,2); + static 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; +} + + +double Element2d :: +CalcJacobianBadnessDirDeriv (const ARRAY<Point2d> & points, + int pi, Vec2d & dir, double & dd) const +{ + int i, j, k, l; + int nip = GetNIP(); + static DenseMatrix trans(2,2), dtrans(2,2), hmat(2,2); + static DenseMatrix pmat, vmat; + + pmat.SetSize (2, GetNP()); + vmat.SetSize (2, GetNP()); + + GetPointMatrix (points, pmat); + + for (i = 1; i <= np; i++) + for (j = 1; j <= 2; j++) + vmat.Elem(j, i) = 0; + // for (j = 1; j <= 2; j++) + vmat.Elem(1, pi) = dir.X(); + vmat.Elem(2, pi) = dir.Y(); + + + + 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 <= 4; j++) + frob += sqr (trans.Get(j)); + frob = sqrt (frob); + + double dfrob = 0; + for (j = 1; j <= 4; j++) + dfrob += trans.Get(j) * dtrans.Get(j); + dfrob = dfrob / frob; + + frob /= 2; + dfrob /= 2; + + + double det = trans.Det(); + double ddet = 0; + + for (j = 1; j <= 2; j++) + { + hmat = trans; + for (k = 1; k <= 2; k++) + hmat.Elem(k, j) = dtrans.Get(k, j); + ddet += hmat.Det(); + } + + + 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 Vec3d & n) const +{ + int i, j; + int nip = GetNIP(); + static DenseMatrix trans(2,2); + static DenseMatrix pmat; + + pmat.SetSize (2, GetNP()); + + Vec3d t1, t2; + n.GetNormal(t1); + Cross (n, t1, t2); + + for (i = 1; i <= nip; i++) + { + const Point3d & p = points.Get(PNum(i)); + pmat.Elem(1, i) = p.X() * t1.X() + p.Y() * t1.Y() + p.Z() * t1.Z(); + pmat.Elem(2, i) = p.X() * t2.X() + p.Y() * t2.Y() + p.Z() * t2.Z(); + } + + 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; + } + + int i; + for (i = 1; i <= GetNIP(); i++) + { + IntegrationPointData * ipd = new IntegrationPointData; + Point2d hp; + GetIntegrationPoint (i, hp, ipd->weight); + ipd->p.X() = hp.X(); + ipd->p.Y() = hp.Y(); + ipd->p.Z() = 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.refflag = 1; + flags.deleted = 0; + order = 1; +} + + +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.refflag = 1; + flags.deleted = 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; + } + order = 1; +} + + +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.refflag = 1; + flags.deleted = 0; + order = 1; +} + + + + + +Element & Element :: operator= (const Element & el2) +{ + int i; + typ = el2.typ; + np = el2.np; + for (i = 0; i < ELEMENT_MAXPOINTS; i++) + pnum[i] = el2.pnum[i]; + index = el2.index; + flags = el2.flags; + order = el2.order; + 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; + } +} + + + +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 +{ + Vec3d v1 = points.Get(PNum(2)) - + points.Get(PNum(1)); + Vec3d v2 = points.Get(PNum(3)) - + points.Get(PNum(1)); + Vec3d 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 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 + case 10: // tet + { + face.SetType(TRIG); + for (int j = 1; j <= 3; j++) + face.PNum(j) = PNum(tetfaces[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; + } + } +} + +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 }, + { 1, 0, 0 }, + { 0, 0, 1 }, + { 1, 0, 1 }, + { 1, 1, 1 }, + { 1, 0, 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])); +} + + + + + + + +void Element :: GetNodesLocalNew (ARRAY<Point3d> & 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; + } + } + + points.SetSize(0); + for (i = 0; i < np; i++) + points.Append (Point3d (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 } }; + + // just a few: + static int tet10trigs[][3] = + { { 2, 8, 9 }, + { 3, 10, 8}, + { 4, 9, 10 }, + { 9, 8, 10 }, + { 3, 1, 4 }, + { 1, 2, 4 }, + { 2, 1, 3 } }; + + 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 = 7; + 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(3); + 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<IntegrationPointData*> ipdtet; +ARRAY<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, Point3d & 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; + switch (typ) + { + case TET: pp = &eltetqp[0][0]; break; + case TET10: pp = &eltet10qp[ip-1][0]; break; + } + + p.X() = pp[0]; + p.Y() = pp[1]; + p.Z() = pp[2]; + weight = pp[3]; +} + +void Element :: +GetTransformation (int ip, const T_POINTS & points, + DenseMatrix & trans) const +{ + int np = GetNP(); + static DenseMatrix pmat(3, np), dshape(3, np); + pmat.SetSize (3, np); + dshape.SetSize (3, np); + + Point3d 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; + switch (GetType()) + { + case TET: dshapep = &ipdtet.Get(ip)->dshape; break; + case TET10: dshapep = &ipdtet10.Get(ip)->dshape; break; + } + + CalcABt (pmat, *dshapep, trans); +} + + + +void Element :: GetShape (const Point3d & p, Vector & shape) const +{ + if (shape.Size() != GetNP()) + { + cerr << "Element::GetShape: Length not fitting" << endl; + return; + } + + switch (typ) + { + case TET: + shape.Elem(1) = 1 - p.X() - p.Y() - p.Z(); + shape.Elem(2) = p.X(); + shape.Elem(3) = p.Y(); + shape.Elem(4) = 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.Elem(5) = 4 * lam1 * lam2; + shape.Elem(6) = 4 * lam1 * lam3; + shape.Elem(7) = 4 * lam1 * lam4; + shape.Elem(8) = 4 * lam2 * lam3; + shape.Elem(9) = 4 * lam2 * lam4; + shape.Elem(10) = 4 * lam3 * lam4; + + shape.Elem(1) = lam1 - + 0.5 * (shape.Elem(5) + shape.Elem(6) + shape.Elem(7)); + shape.Elem(2) = lam2 - + 0.5 * (shape.Elem(5) + shape.Elem(8) + shape.Elem(9)); + shape.Elem(3) = lam3 - + 0.5 * (shape.Elem(6) + shape.Elem(8) + shape.Elem(10)); + shape.Elem(4) = lam4 - + 0.5 * (shape.Elem(7) + shape.Elem(9) + shape.Elem(10)); + break; + } +} + +void Element :: +GetDShape (const Point3d & p, DenseMatrix & dshape) const +{ + int np = GetNP(); + if (dshape.Height() != 3 || dshape.Width() != np) + { + cerr << "Element::DShape: Sizes don't fit" << endl; + return; + } + + int i, j; + double eps = 1e-6; + Vector shaper(np), shapel(np); + + for (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 (j = 1; j <= np; j++) + dshape.Elem(i, j) = (shaper.Get(j) - shapel.Get(j)) / (2 * eps); + } +} + + +void Element :: +GetPointMatrix (const T_POINTS & points, + DenseMatrix & pmat) const +{ + int i; + int np = GetNP(); + if (pmat.Width() != np || pmat.Height() != 3) + { + cerr << "Element::GetPointMatrix: sizes don't fit" << endl; + return; + } + + for (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 i, j; + int nip = GetNIP(); + static DenseMatrix trans(3,3); + static DenseMatrix pmat; + + pmat.SetSize (3, 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 <= 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, Vec3d & dir, double & dd) const +{ + int i, j, k, l; + int nip = GetNIP(); + static DenseMatrix trans(3,3), dtrans(3,3), hmat(3,3); + static 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.X(j); + + + + 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; +} + + + + + +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)); + } + + int i; + for (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.Append (ipd); break; + case TET10: ipdtet10.Append (ipd); break; + default: + PrintSysError ("Element::ComputeIntegrationPoint(2), illegal type ", int(typ)); + } + } +} + + + + + + + + +FaceDescriptor :: FaceDescriptor() +{ + surfnr = domin = + domout = bcprop = 0; + tlosurf = -1; +} + +FaceDescriptor :: +FaceDescriptor(int surfnri, int domini, int domouti, int tlosurfi) +{ + surfnr = surfnri; + domin = domini; + domout = domouti; + tlosurf = tlosurfi; + bcprop = surfnri; +} + +FaceDescriptor :: FaceDescriptor(const Segment & seg) +{ + surfnr = seg.si; + domin = seg.domin+1; + domout = seg.domout+1; + tlosurf = seg.tlosurf+1; + bcprop = 0; +} + +int FaceDescriptor :: SegmentFits (const Segment & seg) +{ + return + surfnr == seg.si && + domin == seg.domin+1 && + domout == seg.domout+1 && + tlosurf == seg.tlosurf+1; +} + + +ostream & operator<<(ostream & s, const FaceDescriptor & fd) +{ + s << "surfnr = " << fd.surfnr + << ", domin = " << fd.domin + << ", domout = " << fd.domout + << ", tlosurf = " << fd.tlosurf + << ", bcprop = " << fd.bcprop; + return s; +} + + + + + + +Identifications :: Identifications (Mesh & amesh) + : mesh(amesh) +{ + identifiedpoints = new INDEX_2_HASHTABLE<int>(100); + maxidentnr = 0; +} + +Identifications :: ~Identifications () +{ + delete identifiedpoints; +} + +void Identifications :: Delete () +{ + delete identifiedpoints; + identifiedpoints = new INDEX_2_HASHTABLE<int>(100); + maxidentnr = 0; +} + +void Identifications :: Add (PointIndex pi1, PointIndex pi2, int identnr) +{ + INDEX_2 pair (pi1, pi2); + identifiedpoints->Set (pair, identnr); + if (identnr > maxidentnr) maxidentnr = identnr; + // 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; +} + +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) const +{ + int i, j; + + identmap.SetSize (mesh.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 Identifications :: GetPairs (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); + } +} + + + + + + + +MeshingParameters :: MeshingParameters () +{ + optimize3d = "cmdmstm"; + optsteps3d = 3; + optimize2d = "smsmsmSmSmSm"; + optsteps2d = 1; + opterrpow = 2; + blockfill = 1; + filldist = 0.1; + safety = 5; + relinnersafety = 3; + uselocalh = 1; + grading = 0.5; + delaunay = 1; + maxh = 1e10; + meshsizefilename = NULL; + startinsurface = 0; + checkoverlap = 1; + checkchartboundary = 1; + curvaturesafety = 2; + parthread = 0; + + elsizeweight = 0; + giveuptol = 10; + maxoutersteps = 5; + starshapeclass = 5; + baseelnp = 0; + sloppy = 1; + + badellimit = 175; + secondorder = 0; +} + +void MeshingParameters :: Print (ostream & ost) const +{ + ost << "Meshing parameters: " << endl + << "maxh = " << maxh << endl + << "grading = " << grading << endl + << "startinsurface = " << startinsurface << endl + << "checkoverlap = " << checkoverlap << endl + << "curvaturesafety = " << curvaturesafety << endl; +} + + + +DebugParameters :: DebugParameters () +{ + slowchecks = 0; + haltsuccess = 0; + haltnosuccess = 0; + haltsegment = 0; + haltsegmentp1 = 0; + haltsegmentp2 = 0; +}; + + + +} diff --git a/Netgen/libsrc/meshing/meshtype.hpp b/Netgen/libsrc/meshing/meshtype.hpp new file mode 100644 index 0000000000..25a131114a --- /dev/null +++ b/Netgen/libsrc/meshing/meshtype.hpp @@ -0,0 +1,919 @@ +#ifndef MESHTYPE +#define MESHTYPE + +/**************************************************************************/ +/* File: meshtype.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Okt. 95 */ +/**************************************************************************/ + +/* + 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 6 + + +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 }; + + + + +// class CSGeometry; + +extern int GetTimeStamp(); +extern int NextTimeStamp(); + +struct PointGeomInfo +{ + int trignum; // for STL Meshing + double u, v; // for OCC Meshing +}; + +inline ostream & operator<< (ostream & ost, const PointGeomInfo & gi) +{ + return (ost << gi.trignum); +} + + + +#define MULTIPOINTGEOMINFO_MAX 100 +class MultiPointGeomInfo +{ + int cnt; + PointGeomInfo mgi[MULTIPOINTGEOMINFO_MAX]; +public: + MultiPointGeomInfo (); + int AddPointGeomInfo (const PointGeomInfo & gi); + void Init (); + void DeleteAll (); + + int GetNPGI () const { return cnt; } + const PointGeomInfo & GetPGI (int i) const { return mgi[i-1]; } +}; + + +struct EdgePointGeomInfo +{ +public: + int edgenr; + double dist; + double u, v; // for OCC Meshing + + EdgePointGeomInfo () + { edgenr = 0; dist = 0; u = v = 0; } +}; + +inline ostream & operator<< (ostream & ost, const EdgePointGeomInfo & gi) +{ + return (ost << gi.edgenr); +} + + + + + + +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 hi; } + PointIndex operator-- (int) { int hi = i; i--; return hi; } + + enum { BASE = 1 }; +}; + +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; } +}; + + + + +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; } +}; + + + +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; } +}; + + + + + + +/** + Point in the mesh. + Contains layer (a new feature in 4.3 for overlapping meshes. + will contain pointtype + */ +class MeshPoint : public Point3d +{ + int layer; +public: + MeshPoint () { ; } + MeshPoint (const Point3d & ap, int alayer = 1) + : Point3d (ap), layer(alayer) { ; } + + void SetPoint (const Point3d & ap) + { Point3d::operator= (ap); } + int GetLayer() const { return layer; } +}; + + + +// typedef MoveableArray<MeshPoint> T_POINTS; +typedef ARRAY<MeshPoint,PointIndex::BASE> T_POINTS; + + +class Element2d; +ostream & operator<<(ostream & s, const Element2d & el); + +/** + Triangle element for surface mesh generation. + */ +class Element2d +{ + /// point numbers + PointIndex pnum[ELEMENT2D_MAXPOINTS]; + /// geom info of corner points + PointGeomInfo geominfo[ELEMENT2D_MAXPOINTS]; + + /// surface nr + int index:16; + /// + ELEMENT_TYPE typ:6; + /// number of points + unsigned int np:3; + bool badel:1; + bool refflag:1; // marked for refinement + bool deleted:1; // element is deleted + + /// order for hp-FEM + unsigned int order:6; +public: + /// + Element2d (int anp = 3); + /// + 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); + /// + 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 order; } + void SetOrder (int aorder) { order = aorder; } + + /// + 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; + /// matrix 2 * np + void GetDShape (const Point2d & p, class DenseMatrix & 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 Vec3d & 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; + } + + void SetRefinementFlag (int rflag = 1) + { refflag = rflag; } + bool TestRefinementFlag () const + { return refflag; } + + int HasFace(const Element2d& el) const; + /// + int meshdocval; +}; + + + + +class IntegrationPointData +{ +public: + Point3d p; + double weight; + Vector shape; + DenseMatrix dshape; +}; + + + + +class Element; +ostream & operator<<(ostream & s, const Element & el); + + + +/** + 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; + /// + struct flagstruct { + 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 deleted:1; // element is deleted, will be removed from array + }; + /// surface or sub-domain index + short int index; + /// order for hp-FEM + unsigned int order:6; + /// stored shape-badness of element + float badness; + +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: return 4; + case TET10: return 4; + case PRISM12: return 6; + default: +#ifdef DEBUG + PrintSysError ("Element3d::GetNV not implemented for typ", typ) +#endif + ; + } + return np; + } + // 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 order; } + void SetOrder (int aorder) { order = aorder; } + + /// + 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<Point3d> & points) const; + void GetNodesLocalNew (ARRAY<Point3d> & 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, Point3d & 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 Point3d & p, class Vector & shape) const; + /// matrix 2 * np + void GetDShape (const Point3d & p, class DenseMatrix & 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, Vec3d & dir, double & dd) const; + + /// + friend ostream & operator<<(ostream & s, const Element & el); + + void SetRefinementFlag (int rflag = 1) + { flags.refflag = rflag; } + int TestRefinementFlag () const + { return flags.refflag; } + + 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; + } +}; + + +class Segment; +ostream & operator<<(ostream & s, const Segment & seg); + + +/** + Edge segment. + */ +class Segment +{ +public: + /// + Segment(); + + friend ostream & operator<<(ostream & s, const Segment & seg); + + /// point index 1 + PointIndex p1; + /// point index 2 + PointIndex p2; + /// edge nr + int edgenr; + /// + unsigned int singedge:1; + /// 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; +}; + + +// class Surface; +class FaceDescriptor; +ostream & operator<< (ostream & s, const FaceDescriptor & fd); + +/// +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; + +public: + FaceDescriptor(); + FaceDescriptor(int surfnri, int domini, int domouti, int tlosurfi); + FaceDescriptor(const Segment & seg); + + 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; } + void SetSurfNr (int sn) { surfnr = sn; } + void SetDomainIn (int di) { domin = di; } + void SetDomainOut (int dom) { domout = dom; } + void SetBCProperty (int bc) { bcprop = bc; } + + friend ostream & operator<<(ostream & s, const FaceDescriptor & fd); +}; + + + + + + +class 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 + */ + 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 + **/ + 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; + /// file for meshsize + const char * meshsizefilename; + /// start surfacemeshing from everywhere in surface + int startinsurface; + /// check overlapping surfaces (debug) + int checkoverlap; + /// 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 + 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; + + /// + int secondorder; + /// high order element curvature + int elementorder; + /// quad-dominated surface meshing + int quad; + /// + int inverttets; + /// + int inverttrigs; + /// + MeshingParameters (); + /// + void Print (ostream & ost) const; +}; + +class DebugParameters +{ +public: + /// + int debugoutput; + /// use slow checks + int slowchecks; + /// + int haltsuccess; + /// + int haltnosuccess; + /// + 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 +{ +private: + Mesh & mesh; + + /// identify points (thin layers, periodic b.c.) + INDEX_2_HASHTABLE<int> * identifiedpoints; + + /// number of identifications (or, actually used identifications ?) + int maxidentnr; + +public: + /// + Identifications (Mesh & amesh); + /// + ~Identifications (); + + void Delete (); + + /* + Identify points pi1 and pi2, due to + identification nr identnr + */ + void Add (PointIndex pi1, PointIndex pi2, int identnr); + + + int Get (PointIndex pi1, PointIndex pi2) const; + int GetSymmetric (PointIndex pi1, PointIndex pi2) 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) const; + /// + void GetPairs (int identnr, ARRAY<INDEX_2> & identpairs) const; + /// + int GetMaxNr () const { return maxidentnr; } + +}; + + + + + + + +#endif diff --git a/Netgen/libsrc/meshing/msghandler.cpp b/Netgen/libsrc/meshing/msghandler.cpp new file mode 100644 index 0000000000..8d2bb429ee --- /dev/null +++ b/Netgen/libsrc/meshing/msghandler.cpp @@ -0,0 +1,186 @@ +//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, 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")); +} + +ARRAY<MyStr*> msgstatus_stack(0); +MyStr* msgstatus = NULL; + +void ResetStatus() +{ + SetStatMsg("idle"); + + if (msgstatus != NULL) + { + delete msgstatus; + } + int i; + for (i = 1; i <= msgstatus_stack.Size(); i++) + { + delete msgstatus_stack.Get(i); + } + + msgstatus_stack.SetSize(0); + msgstatus = NULL; + multithread.task = ""; + multithread.percent = 100.; +} + +void PushStatus(const MyStr& s) +{ + if (msgstatus == NULL) + { + SetStatMsg("idle"); + } + msgstatus_stack.Append(msgstatus); + msgstatus = NULL; + + SetStatMsg(s); + // multithread.task = ""; +} +void PushStatusF(const MyStr& s) +{ + if (msgstatus == NULL) + { + SetStatMsg("idle"); + } + msgstatus_stack.Append(msgstatus); + msgstatus = NULL; + + SetStatMsg(s); + // multithread.task = ""; + PrintFnStart(s); +} + +void PopStatus() +{ + SetThreadPercent(100.); + if (msgstatus_stack.Size()) + { + if (msgstatus != NULL) + { + delete msgstatus; + } + msgstatus = msgstatus_stack.Get(msgstatus_stack.Size()); + msgstatus_stack.SetSize(msgstatus_stack.Size()-1); + multithread.task = msgstatus->c_str(); + } + else + { + PrintSysError("PopStatus failed"); + } +} +/* +void SetStatMsgF(const MyStr& s) +{ + PrintFnStart(s); + SetStatMsg(s); +} +*/ +void SetStatMsg(const MyStr& s) +{ + if (msgstatus != NULL) + { + delete msgstatus; + } + msgstatus = new MyStr(s); + multithread.task = msgstatus->c_str(); +} + +void SetThreadPercent(double percent) +{ + multithread.percent = percent; +} + + +} diff --git a/Netgen/libsrc/meshing/msghandler.hpp b/Netgen/libsrc/meshing/msghandler.hpp new file mode 100644 index 0000000000..b7d4481866 --- /dev/null +++ b/Netgen/libsrc/meshing/msghandler.hpp @@ -0,0 +1,47 @@ +#ifndef FILE_MSGHANDLER +#define FILE_MSGHANDLER + +/**************************************************************************/ +/* File: msghandler.hh */ +/* Author: Johannes Gerstmayr */ +/* Date: 20. Nov. 99 */ +/**************************************************************************/ + + +extern void PrintDot(char ch = '.'); + + +//Message Pipeline: + +//importance: importance of message: 1=very important, 3=middle, 5=low, 7=unimportant +extern 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=""); +// CR without line-feed +extern 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 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 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 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 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 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 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 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 void SetStatMsg(const MyStr& s); + +extern void PushStatus(const MyStr& s); +extern void PushStatusF(const MyStr& s); +extern void PopStatus(); +extern void SetThreadPercent(double percent); + + +#endif + diff --git a/Netgen/libsrc/meshing/netrule2.cpp b/Netgen/libsrc/meshing/netrule2.cpp new file mode 100644 index 0000000000..c0acd4938d --- /dev/null +++ b/Netgen/libsrc/meshing/netrule2.cpp @@ -0,0 +1,212 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + +netrule :: netrule () +{ + name = new char[1]; + name[0] = char(0); + quality = 0; +} + +netrule :: ~netrule() +{ + delete name; +} + + +/* +void netrule :: GetFreeArea (ARRAY<Point2d> & afreearea) + { + int i; + + afreearea.SetSize (freearea.Size()); + for (i = 1; i <= freearea.Size(); i++) + afreearea[i] = freearea[i]; + } +*/ + + +void netrule :: SetFreeZoneTransformation (const Vector & devp, int tolclass) +{ + int i; + double lam1 = 1.0/tolclass; + double lam2 = 1-lam1; + + double mem1[100], mem2[100], mem3[100]; + + int vs = oldutofreearea.Height(); + FlatVector devfree(vs, mem1); + FlatVector devfree1(vs, mem2); + FlatVector devfree2(vs, mem3); + + oldutofreearea.Mult (devp, devfree1); + oldutofreearealimit.Mult (devp, devfree2); + devfree.Set2 (lam1, devfree1, lam2, devfree2); + + transfreezone.SetSize (freezone.Size()); + + + int fzs = transfreezone.Size(); + + if (fzs > 0) + { + transfreezone[0].X() = lam1 * freezone[0].X() + lam2 * freezonelimit[0].X() + devfree[0]; + transfreezone[0].Y() = lam1 * freezone[0].Y() + lam2 * freezonelimit[0].Y() + devfree[1]; + fzmaxx = fzminx = transfreezone[0].X(); + fzmaxy = fzminy = transfreezone[0].Y(); + } + + for (i = 1; 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 (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 (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 *= 1/sqrt (len2); + + 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 +{ + int i; + + for (i = 1; i <= transfreezone.Size(); i++) + { + if (freesetinequ.Get(i, 1) * p.X() + freesetinequ.Get(i, 2) * p.Y() + + freesetinequ.Get(i, 3) > 0) return 0; + } + return 1; +} + +int netrule :: IsLineInFreeZone2 (const Point2d & p1, const Point2d & p2) const +{ + int i; + int left, right, allleft, allright; + double nx, ny, nl, c; + + 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 (i = 1; i <= transfreezone.Size(); i++) + { + if (freesetinequ.Get(i, 1) * p1.X() + freesetinequ.Get(i, 2) * p1.Y() + + freesetinequ.Get(i, 3) > -1e-5 && + freesetinequ.Get(i, 1) * p2.X() + freesetinequ.Get(i, 2) * p2.Y() + + freesetinequ.Get(i, 3) > -1e-5 + ) return 0; + } + + nx = (p2.Y() - p1.Y()); + ny = -(p2.X() - p1.X()); + nl = sqrt (nx * nx + ny * ny); + if (nl > 1e-8) + { + nx /= nl; + ny /= nl; + c = - (p1.X() * nx + p1.Y() * ny); + + allleft = 1; + allright = 1; + + for (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 i, n; + n = transfreezone.Size(); + for (i = 1; i <= n; i++) + { + if (! CCW (transfreezone.Get(i), + transfreezone.Get(i % n + 1), + transfreezone.Get( (i+1) % n + 1 ) ) ) + 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 * tf = &linetolerances.Get(li); + return tf->f1 * dx * dx + tf->f2 * dx * dy + tf->f3 * dy * dy; +} + + + + +/* +int GetNRules () + { + return rules.Size(); + } +*/ + + + + + + + + + + + +} diff --git a/Netgen/libsrc/meshing/netrule3.cpp b/Netgen/libsrc/meshing/netrule3.cpp new file mode 100644 index 0000000000..b6c5967058 --- /dev/null +++ b/Netgen/libsrc/meshing/netrule3.cpp @@ -0,0 +1,1143 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +// #define MARK +// #include <prof.h> + + +namespace netgen +{ + + +vnetrule :: vnetrule () +{ + name = ""; + quality = 0; +} + +vnetrule :: ~vnetrule () +{ + int i; + if (strlen(name)) + delete name; + for (i = 1; i <= freefaces.Size(); i++) + delete freefaces.Elem(i); + for (i = 1; i <= freesets.Size(); i++) + delete freesets.Elem(i); + for (i = 1; i <= freeedges.Size(); i++) + delete freeedges.Elem(i); + for (i = 1; i <= freefaceinequ.Size(); i++) + delete freefaceinequ.Elem(i); + delete oldutofreezone; + delete oldutofreezonelimit; +} + +int vnetrule :: TestFlag (char flag) const +{ + int i; + for (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; + + // MARK (setfz1); + + 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.Elem(j) = allp.Get(i+3*j-3); + + 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.Elem(j); + } + + // 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; + + + static ARRAY<int> 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; + static 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 lam1 = rs1 * vii22 - rs2 * vii12; + double lam2 = rs2 * vii11 - rs1 * vii12; + + if (fabs (lam1) > fabs (lam2)) + { + if (lam1 < 0) + an *= -1; + } + else + { + if (lam2 < 0) + an *= -1; + } + + + if (lam1 * lam2 < 0 && 0) + { + if (fabs (lam1) > 1e-14 && fabs (lam2) > 1e-14) + { + // (*mycout) << "lam1 lam2 < 0" << endl; + (*testout) << "lami 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) << "lami = " << lam1 << ", " << lam2 << 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 lam1 = rs1 * vii22 - rs2 * vii12; + double lam2 = rs2 * vii11 - rs1 * vii12; + + // (*testout) << "lam1, lam2 = " << lam1 << ", " << lam2 << endl; + + + if (fabs (lam1) > fabs (lam2)) + { + if (lam1 < 0) + an *= -1; + } + else + { + if (lam2 < 0) + an *= -1; + } + + + if (lam1 * lam2 < 0) + { + if (fabs (lam1) > 1e-14 && fabs (lam2) > 1e-14) + { + // (*mycout) << "lam1 lam2 < 0" << endl; + (*testout) << "lami 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) << "lami = " << lam1 << ", " << lam2 << 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; + + + static ARRAY<int> 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; + } + + static ARRAY<int> 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/Netgen/libsrc/meshing/parser2.cpp b/Netgen/libsrc/meshing/parser2.cpp new file mode 100644 index 0000000000..402207c259 --- /dev/null +++ b/Netgen/libsrc/meshing/parser2.cpp @@ -0,0 +1,550 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +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 == ',') + 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); + + 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, "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 = 0; + tolerances.Elem(noldp).f2 = 0; + tolerances.Elem(noldp).f3 = 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; // ')' + + 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; + + ist >> ch; + while (ch != ';') + { + 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' + } + + 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; // ')' + + 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 == ',') + { + ist >> elements.Last().PNum(2); + ist >> ch; // ',' + } + if (ch == ',') + { + ist >> elements.Last().PNum(3); + ist >> ch; // ',' + } + if (ch == ',') + { + 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)); + } + } + +} + + + + +extern const char * triarules[]; +extern const char * quadrules[]; + +void Meshing2 :: LoadRules (const char * filename) +{ + char buf[256]; + istream * ist; + char *tr1 = NULL; + + /* + 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) + { + hcp = triarules; + PrintMessage (3, "load internal triangle rules"); + } + else + { + hcp = quadrules; + PrintMessage (3, "load internal quad rules"); + // LoadRules ("rules/quad.rls"); + } + + int len = 0; + while (*hcp) + { + len += strlen (*hcp); + hcp++; + } + tr1 = new char[len+1]; + tr1[0] = 0; + + + if (!mparam.quad) + hcp = triarules; + else + hcp = quadrules; + + + char * tt1 = tr1; + while (*hcp) + { + strcat (tt1, *hcp); + tt1 += strlen (*hcp); + hcp++; + } + + 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) + { + netrule * rule = new netrule; + rule -> LoadRule(*ist); + rules.Append (rule); + } + } + + delete ist; + delete [] tr1; +} + +} diff --git a/Netgen/libsrc/meshing/parser3.cpp b/Netgen/libsrc/meshing/parser3.cpp new file mode 100644 index 0000000000..7bf6e513ac --- /dev/null +++ b/Netgen/libsrc/meshing/parser3.cpp @@ -0,0 +1,987 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +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 == ',') + 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); + + 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 == ',') + { + 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 == ',') + { + 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 i, j, k, nfp; + Point3d p; + + 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 i, j, k, nfp; + Point3d p; + + 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 == ',') + { + // elements.Last().SetNP(2); + ist >> elements.Last().PNum(2); + ist >> ch; // ',' + } + if (ch == ',') + { + // elements.Last().SetNP(3); + ist >> elements.Last().PNum(3); + ist >> ch; // ',' + } + if (ch == ',') + { + // elements.Last().SetNP(4); + elements.Last().SetType(TET); + ist >> elements.Last().PNum(4); + ist >> ch; // ',' + } + if (ch == ',') + { + // elements.Last().SetNP(5); + elements.Last().SetType(PYRAMID); + ist >> elements.Last().PNum(5); + ist >> ch; // ',' + } + if (ch == ',') + { + // 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 (i = 1; i <= 3; i++) + { + for (j = 1; j <= points.Size(); j++) + vp.Elem(j) = points.Get(j).X(i); + oldutofreezone->Mult(vp, vfp); + for (j = 1; j <= freezone.Size(); j++) + freezone.Elem(j).X(i) = vfp.Get(j); + } + // 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)); + } + + + { + char ok; + 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 <= elements.Size(); i++) + if (elements.Get(i).GetNP() == 6) + { + 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); + + int 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)); + } + } + + + //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 edge(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)) + { + edge.I(1) = f1.I(f11); + edge.I(2) = f1.I(f12); + } + // (*testout) << "edge = " << edge.I(1) << "-" << edge.I(2) << endl; + // (*testout) << "ind = " << ind << " edge = " << edge << endl; + for (int eli = 1; eli <= GetNOldF(); eli++) + { + if (GetNP(eli) == 4) + { + for (int elr = 1; elr <= 4; elr++) + { + if (GetPointNrMod (eli, elr) == edge.I(1) && + GetPointNrMod (eli, elr+2) == edge.I(2)) + { + /* + (*testout) << "edge is diagonal of rectangle" << endl; + (*testout) << "edge = " << edge.I(1) << "-" << edge.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; + int 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++; + } + + 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/Netgen/libsrc/meshing/prism2rls.cpp b/Netgen/libsrc/meshing/prism2rls.cpp new file mode 100644 index 0000000000..baf0bef388 --- /dev/null +++ b/Netgen/libsrc/meshing/prism2rls.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/Netgen/libsrc/meshing/pyramid2rls.cpp b/Netgen/libsrc/meshing/pyramid2rls.cpp new file mode 100644 index 0000000000..a97e7f13e5 --- /dev/null +++ b/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/Netgen/libsrc/meshing/pyramidrls.cpp b/Netgen/libsrc/meshing/pyramidrls.cpp new file mode 100644 index 0000000000..d4e997c1fe --- /dev/null +++ b/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/Netgen/libsrc/meshing/quadrls.cpp b/Netgen/libsrc/meshing/quadrls.cpp new file mode 100644 index 0000000000..01555b72ea --- /dev/null +++ b/Netgen/libsrc/meshing/quadrls.cpp @@ -0,0 +1,743 @@ +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 (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",\ +"\n",\ +"newpoints\n",\ +"(0, 1) { } { 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.6) { 0.6 X2, 0.6 Y2 } { 0.6 Y3 };\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, 0.5) { 0.5 X2, 0.5 Y2 } { 0.5 Y3 };\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",\ +"rule \"Quad Right PL (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",\ +"\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.2 X2, 0.6 X3, 0.6 X4 } { -0.2 Y2, 0.6 Y3, 0.6 Y4 };\n",\ +"(0, 1) { 1 X4 } { 1 Y4 };\n",\ +"(-0.2, 0.5) { -0.2 X2, -0.2 X3, 0.6 X4 } { -0.2 Y2, -0.2 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",\ +"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 (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",\ +"\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 (1)\"\n",\ +"\n",\ +"quality 1\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.2 X3 } { 0.6 Y2, 0.6 Y4, -0.2 Y3 };\n",\ +"(1, 1) { 1 X4 } { 1 Y4 };\n",\ +"(0.5, 1.2) { -0.2 X2, 0.6 X3, 0.6 X4 } { -0.2 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",\ +"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 (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",\ +"\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",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\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/Netgen/libsrc/meshing/refine.cpp b/Netgen/libsrc/meshing/refine.cpp new file mode 100644 index 0000000000..c14979693e --- /dev/null +++ b/Netgen/libsrc/meshing/refine.cpp @@ -0,0 +1,549 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + void Refinement :: Refine (Mesh & mesh, int /* levels */) + { + int i, j, k; + + + // reduce 2nd order + mesh.ComputeNVertices(); + mesh.SetNP(mesh.GetNV()); + + + + // for (l = 1; l <= levels; l++) + // { + INDEX_2_HASHTABLE<int> between(mesh.GetNP() + 5); + + int oldne, oldns, oldnf; + + // refine edges + + + ARRAY<EdgePointGeomInfo> epgi; + + oldns = mesh.GetNSeg(); + + for (i = 1; i <= oldns; i++) + { + const Segment & el = mesh.LineSegment(i); + + INDEX_2 i2(el.p1, el.p2); + i2.Sort(); + + int pnew; + EdgePointGeomInfo ngi; + + if (between.Used(i2)) + { + pnew = between.Get(i2); + ngi = epgi.Get(pnew); + } + else + { + Point3d pb; + pb = Center (mesh.Point (el.p1), + mesh.Point (el.p2)); + + PointBetween (mesh.Point (el.p1), + mesh.Point (el.p2), 0.5, + el.surfnr1, el.surfnr2, + el.epgeominfo[0], el.epgeominfo[1], + pb, ngi); + + pnew = mesh.AddPoint (pb); + + between.Set (i2, pnew); + + if (pnew > epgi.Size()) + epgi.SetSize (pnew); + epgi.Elem(pnew) = ngi; + + (*testout) << "ref edge, oldgi = " + << el.epgeominfo[0] << " - " << el.epgeominfo[1] + << ", new gi = " << ngi << endl; + + } + + Segment ns1 = el; + Segment ns2 = el; + ns1.p2 = pnew; + ns1.epgeominfo[1] = ngi; + ns2.p1 = pnew; + ns2.epgeominfo[0] = ngi; + + mesh.LineSegment(i) = ns1; + mesh.AddSegment (ns2); + } + + + + (*testout) << "refine surfaces" << endl; + // refine surface elements + + ARRAY<PointGeomInfo> surfgi (8*mesh.GetNP()); + for (i = 1; i <= surfgi.Size(); i++) + surfgi.Elem(i).trignum = -1; + + oldnf = mesh.GetNSE(); + for (i = 1; i <= oldnf; i++) + { + int j, k; + const Element2d & el = mesh.SurfaceElement(i); + + 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++) + { + int pi1 = pnums.Elem(betw[j][0]); + int pi2 = pnums.Elem(betw[j][1]); + + INDEX_2 i2 (pi1, pi2); + i2.Sort(); + + + + Point3d 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); + + + /* + if (between.Used(i2)) + { + pnums.Elem(4+j) = between.Get(i2); + pgis.Elem(4+j) = surfgi.Get(pnums.Elem(4+j)); + } + else + { + Point3d 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(4+j)); + + 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); + + (*testout) << "ref face, oldgi = " + << el.GeomInfoPi (betw[j][0]) << " - " + << el.GeomInfoPi (betw[j][1]) + << ", new gi = " << pgis.Elem(4+j) << endl; + + } + */ + } + + 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(i) = nel; + else + mesh.AddSurfaceElement(nel); + } + break; + } + case QUAD: + case QUAD6: + { + 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 }, + { 1, 3, 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 + { + Point3d 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(i) = nel; + else + mesh.AddSurfaceElement(nel); + } + break; + } + default: + PrintSysError ("Refine: undefined surface element type ", int(el.GetType())); + } + } + + (*testout) << "refine volume" << endl; + + // refine volume elements + oldne = mesh.GetNE(); + for (i = 1; i <= oldne; i++) + { + int j, k; + const Element & el = mesh.VolumeElement(i); + 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 int reverse[8] = + { + 0, 0, 0, 0, 0, 1, 0, 1 + }; + + 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 = 1 - nel.flags.reverse; + Swap (nel.PNum(3), nel.PNum(4)); + } + + if (j == 0) + mesh.VolumeElement(i) = nel; + else + mesh.AddVolumeElement (nel); + } + } + + // 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 <= between.GetNBags(); j++) + for (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); + } + } + + } + + + + + + int cnttrials = 10; + int wrongels = 0; + for (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<Point3d> should(np); + ARRAY<Point3d> can(np); + for (i = 1; i <= np; i++) + { + should.Elem(i) = can.Elem(i) = mesh.Point(i); + } + for (i = 1; i <= between.GetNBags(); i++) + for (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 (i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & sel = mesh.SurfaceElement(i); + for (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 (i = 1; i <= np; i++) + if (boundp.Test(i)) + { + for (j = 1; j <= 3; j++) + mesh.Point(i).X(j) = + lam * should.Get(i).X(j) + + (1-lam) * can.Get(i).X(j); + } + else + mesh.Point(i) = can.Get(i); + + + BitArray free (mesh.GetNP()), fhelp(mesh.GetNP()); + free.Clear(); + for (i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement(i); + if (el.Volume(mesh.Points()) < 0) + for (j = 1; j <= el.GetNP(); j++) + free.Set (el.PNum(j)); + } + for (k = 1; k <= 3; k++) + { + fhelp.Clear(); + for (i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement(i); + int freeel = 0; + for (j = 1; j <= el.GetNP(); j++) + if (free.Test(el.PNum(j))) + freeel = 1; + if (freeel) + for (j = 1; j <= el.GetNP(); j++) + fhelp.Set (el.PNum(j)); + } + free.Or (fhelp); + } + + (*testout) << "smooth points: " << endl; + for (i = 1; i <= free.Size(); i++) + if (free.Test(i)) + (*testout) << "p " << i << endl; + + (*testout) << "surf points: " << endl; + for (i = 1; i <= mesh.GetNSE(); i++) + for (j = 1; j <= 3; j++) + (*testout) << mesh.SurfaceElement(i).PNum(j) << endl; + + + + mesh.CalcSurfacesOfNode(); + free.Invert(); + mesh.FixPoints (free); + mesh.ImproveMesh (OPT_REST); + + + wrongels = 0; + for (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 (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 (i = 1; i <= np; i++) + can.Elem(i) = mesh.Point(i); + } + } + + if (cnttrials <= 0) + { + cerr << "ERROR: Sorry, reverted elements" << endl; + } + + mesh.ComputeNVertices(); + (*testout) << "refine done" << endl; + + } +} diff --git a/Netgen/libsrc/meshing/ruler2.cpp b/Netgen/libsrc/meshing/ruler2.cpp new file mode 100644 index 0000000000..700a3c4f70 --- /dev/null +++ b/Netgen/libsrc/meshing/ruler2.cpp @@ -0,0 +1,642 @@ +#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> & llines, + int maxlegalline, + ARRAY<Element2d> & elements, + ARRAY<INDEX> & dellines, int tolerance) +{ + int i, j, ri, nlok, npok, incnpok, refpi, locli = 0; + + double maxerr = 0.5 + 0.3 * tolerance; + double minelerr = 2 + 0.5 * tolerance * tolerance; + + + int ok, found; + netrule * rule; + Vector oldu, newu; + Point2d np; + Vec2d linevec; + int oldnp; + INDEX_2 loclin; + double hf, elerr; + int noldlp, noldll; + int loctestmode; + + static ARRAY<int> pused, lused; + static ARRAY<int> pmap, lmap, pfixed; + static ARRAY<int> pnearness, lnearness; + + static ARRAY<Point2d> tempnewpoints; + static ARRAY<INDEX_2> tempnewlines; + static ARRAY<int> tempdellines; + static ARRAY<Element2d> tempelements; + + + + elements.SetSize (0); + dellines.SetSize (0); + + noldlp = lpoints.Size(); + noldll = llines.Size(); + + pused.SetSize (maxlegalpoint); + lused.SetSize (maxlegalline); + pnearness.SetSize (noldlp); + lnearness.SetSize (llines.Size()); + + + testmode = debugparam.debugoutput; + loctestmode = testmode; + + if (loctestmode) + { + (*testout) << endl << endl << "Check new environment" << endl; + (*testout) << "tolerance = " << tolerance << endl; + for (i = 1; i <= lpoints.Size(); i++) + (*testout) << "P" << i << " = " << lpoints.Get(i) << endl; + (*testout) << endl; + for (i = 1; i <= llines.Size(); i++) + (*testout) << "(" << llines.Get(i).I1() << "-" << llines.Get(i).I2() << ")" << endl; + } + + // check every rule + + found = 0; + + + for (i = 1; i <= noldlp; i++) + pnearness.Set(i, 1000); + + for (j = 1; j <= 2; j++) + pnearness.Set(llines.Get(1).I(j), 0); + + + do + { + ok = 1; + for (i = 1; i <= maxlegalline; i++) + { + const INDEX_2 & hline = llines.Get(i); + + /* + int minn = INT_MAX-1; + for (j = 1; j <= 2; j++) + { + int hi = pnearness.Get(hline.I(j)); + if (hi < minn) minn = hi; + } + */ + int minn = pnearness.Get(hline.I1()); + int minn2 = pnearness.Get(hline.I2()); + if (minn2 < minn) + minn = minn2; + + /* + for (j = 1; j <= 2; j++) + { + int hpi = hline.I(j); + if (pnearness.Get(hpi) > minn+1) + { + ok = 0; + pnearness.Set(hpi, minn+1); + } + } + */ + int hpi = hline.I1(); + if (pnearness.Get(hpi) > minn+1) + { + ok = 0; + pnearness.Set(hpi, minn+1); + } + hpi = hline.I2(); + if (pnearness.Get(hpi) > minn+1) + { + ok = 0; + pnearness.Set(hpi, minn+1); + } + } + } + while (!ok); + + for (i = 1; i <= maxlegalline /* lnearness.Size() */; i++) + { + lnearness.Set(i, 0); + for (j = 1; j <= 2; j++) + lnearness.Elem(i) += pnearness.Get(llines.Get(i).I(j)); + } + + + +#ifdef MARK + MARK (applyrules2m1); +#endif + + for (ri = 1; ri <= rules.Size(); ri++) + { +#ifdef MARK + MARK (applyrules2m1a); +#endif + + rule = rules.Get(ri); + + if (loctestmode) + (*testout) << "Rule " << rule->Name() << endl; + + if (rule->GetQuality() > tolerance) continue; + + pmap.SetSize (rule->GetNP()); + lmap.SetSize (rule->GetNL()); + + for (i = 1; i <= lused.Size(); i++) + lused.Set (i, 0); + for (i = 1; i <= pused.Size(); i++) + pused.Set (i, 0); + for (i = 1; i <= pmap.Size(); i++) + pmap.Set(i, 0); + for (i = 1; i <= lmap.Size(); i++) + lmap.Set(i, 0); + + lused.Set (1, 1); + lmap.Set (1, 1); + + for (j = 1; j <= 2; j++) + { + pmap.Elem(rule->GetPointNr (1, j)) = llines.Get(1).I(j); + pused.Elem(llines.Get(1).I(j))++; + } + + + nlok = 2; + + while (nlok >= 2) + { + +#ifdef MARK + MARK (applyrules2m2b); +#endif + + + if (nlok <= rule->GetNOldL()) + + { + ok = 0; + while (!ok && lmap.Get(nlok) < maxlegalline /* llines.Size() */) + { + lmap.Elem(nlok)++; + locli = lmap.Get(nlok); + + if (!lused.Get(locli) && + lnearness.Get(locli) <= rule->GetLNearness (nlok) ) + { + ok = 1; + + loclin = llines.Get(locli); + + linevec.X() = lpoints.Get (loclin.I2()).X() - + lpoints.Get (loclin.I1()).X(); + linevec.Y() = lpoints.Get (loclin.I2()).Y() - + lpoints.Get (loclin.I1()).Y(); + + if (rule->CalcLineError (nlok, linevec) > maxerr) + ok = 0; + + for (j = 1; j <= 2 && ok; j++) + { + refpi = rule->GetPointNr (nlok, j); + + if (pmap.Get(refpi) != 0) + { + if (pmap.Get(refpi) != loclin.I(j)) + ok = 0; + } + else + { + if (rule->CalcPointDist (refpi, lpoints.Get(loclin.I(j))) > maxerr + || !legalpoints.Get(loclin.I(j)) + || pused.Get(loclin.I(j))) + ok = 0; + } + } + } + } + + if (ok) + { + lused.Set (locli, 1); + for (j = 1; j <= 2; j++) + { + pmap.Set(rule->GetPointNr (nlok, j), loclin.I(j)); + pused.Elem(loclin.I(j))++; + } + + nlok++; + } + else + { + lmap.Elem(nlok) = 0; + nlok--; + + lused.Set (lmap.Get(nlok), 0); + for (j = 1; j <= 2; j++) + { + pused.Elem(llines.Get(lmap.Get(nlok)).I(j)) --; + if (! pused.Get (llines.Get (lmap.Get (nlok)).I(j))) + pmap.Set (rule->GetPointNr (nlok, j), 0); + } + } + } + + else + + { + +#ifdef MARK + MARK (applyrules2mc); +#endif + + + // all lines are mapped !! + + // map also all points: + + npok = 1; + incnpok = 1; + + pfixed.SetSize (pmap.Size()); + for (i = 1; i <= pmap.Size(); i++) + pfixed.Elem(i) = (pmap.Get(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 /* lpoints.Size() */) + { + 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 + + { +#ifdef MARK + MARK (applyrules2m2d); +#endif + + if (ok) + { + foundmap.Elem(ri)++; + } + + if (loctestmode) + (*testout) << "lines and points mapped" << endl; + + oldu.SetSize (2 * rule->GetNOldP()); + + for (i = 1; i <= rule->GetNOldP(); i++) + { + // ui = lpoints.Get(pmap.Get(i)) - rule->GetPoint(i); + Vec2d ui(rule->GetPoint(i), lpoints.Get(pmap.Get(i))); + oldu.Set (2*i-1, ui.X()); + oldu.Set (2*i , ui.Y()); + } + + rule -> SetFreeZoneTransformation (oldu, tolerance); + + ok = 1; + + if (!rule->ConvexFreeZone()) + { + ok = 0; + if (loctestmode) (*testout) << "freezone not convex" << endl; + } + + // check freezone: + + for (i = 1; i <= maxlegalpoint && ok; i++) + { + if ( !pused.Get(i) && + rule->IsInFreeZone (lpoints.Get(i)) ) + { + ok = 0; + if (loctestmode) + (*testout) << "Point " << i << " in freezone" << endl; + } + } + + + for (i = maxlegalpoint+1; i <= lpoints.Size() && ok; i++) + { + if ( rule->IsInFreeZone (lpoints.Get(i)) ) + { + ok = 0; + if (loctestmode) + (*testout) << "Point " << i << " in freezone" << endl; + } + } + + for (i = 1; i <= maxlegalline && ok; i++) + { + if (!lused.Get(i) && + rule->IsLineInFreeZone (lpoints.Get(llines.Get(i).I1()), + lpoints.Get(llines.Get(i).I2()))) + { + ok = 0; + if (loctestmode) + (*testout) << "line " << llines.Get(i).I1() << "-" + << llines.Get(i).I2() << " in freezone" << endl; + } + } + for (i = maxlegalline+1; i <= llines.Size() && ok; i++) + { + if (rule->IsLineInFreeZone (lpoints.Get(llines.Get(i).I1()), + lpoints.Get(llines.Get(i).I2()))) + { + ok = 0; + if (loctestmode) + (*testout) << "line " << llines.Get(i).I1() << "-" + << llines.Get(i).I2() << " in freezone" << endl; + } + } + + + + // 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) + { + if (loctestmode) + (*testout) << "rule ok" << endl; + + // newu = rule->GetOldUToNewU() * oldu; + if (rule->GetNOldP() < rule->GetNP()) + { + newu.SetSize (rule->GetOldUToNewU().Height()); + rule->GetOldUToNewU().Mult (oldu, newu); + } + + // Setze neue Punkte: + + oldnp = rule->GetNOldP(); + + for (i = oldnp + 1; i <= rule->GetNP(); i++) + { + np = rule->GetPoint(i); + np.X() += newu.Elem (2 * (i-oldnp) - 1); + np.Y() += newu.Elem (2 * (i-oldnp)); + + pmap.Elem(i) = lpoints.Append (np); + } + + // Setze neue Linien: + + for (i = rule->GetNOldL() + 1; i <= rule->GetNL(); i++) + { + llines.Append (INDEX_2 (pmap.Get(rule->GetPointNr (i, 1)), + pmap.Get(rule->GetPointNr (i, 2)))); + } + + + // delete old lines: + + for (i = 1; i <= rule->GetNDelL(); i++) + dellines.Append (lmap.Get(rule->GetDelLine(i))); + + // insert new elements: + + for (i = 1; i <= rule->GetNE(); i++) + { + elements.Append (rule->GetElement(i)); + for (j = 1; j <= elements.Get(i).GetNP(); j++) + elements.Elem(i).PNum(j) = pmap.Get(elements.Get(i).PNum(j)); + } + + + elerr = 0; + for (i = 1; i <= elements.Size(); i++) + { + if (!mparam.quad) + hf = CalcElementBadness (lpoints, elements.Get(i)); + else + hf = elements.Get(i).CalcJacobianBadness (lpoints) * 5; + if (loctestmode) + (*testout) << "r " << rule->Name() << "bad = " << hf << endl; + if (hf > elerr) elerr = hf; + } + + if (loctestmode) + (*testout) << "error = " << elerr; + + + canuse.Elem(ri) ++; + + if (elerr < minelerr) + { + + if (testmode) + { + (*testout) << "rule = " << rule->Name() << endl; + (*testout) << "class = " << tolerance << endl; + (*testout) << "lpoints: " << endl; + for (i = 1; i <= lpoints.Size(); i++) + (*testout) << lpoints.Get(i) << endl; + (*testout) << "llines: " << endl; + for (i = 1; i <= llines.Size(); i++) + (*testout) << llines.Get(i).I1() << " " << llines.Get(i).I2() << endl; + + (*testout) << "Freezone: "; + for (i = 1; i <= rule -> GetTransFreeZone().Size(); i++) + (*testout) << rule->GetTransFreeZone().Get(i) << endl; + } + + + + minelerr = elerr; + found = ri; + + tempnewpoints.SetSize (0); + for (i = noldlp+1; i <= lpoints.Size(); i++) + tempnewpoints.Append (lpoints.Get(i)); + + tempnewlines.SetSize (0); + for (i = noldll+1; i <= llines.Size(); i++) + tempnewlines.Append (llines.Get(i)); + + tempdellines.SetSize (0); + for (i = 1; i <= dellines.Size(); i++) + tempdellines.Append (dellines.Get(i)); + + tempelements.SetSize (0); + for (i = 1; i <= elements.Size(); i++) + tempelements.Append (elements.Get(i)); + } + + lpoints.SetSize (noldlp); + llines.SetSize (noldll); + dellines.SetSize (0); + elements.SetSize (0); + ok = 0; + + } + + + npok = rule->GetNOldP(); + incnpok = 0; + } + } + + nlok = rule->GetNOldL(); + + lused.Set (lmap.Get(nlok), 0); + + for (j = 1; j <= 2; j++) + { + refpi = rule->GetPointNr (nlok, j); + pused.Elem(pmap.Get(refpi))--; + + if (pused.Get(pmap.Get(refpi)) == 0) + { + pmap.Set(refpi, 0); + } + } + } + } + } + + +#ifdef MARK + MARK (applyrules2m3); +#endif + + + if (found) + { + for (i = 1; i <= tempnewpoints.Size(); i++) + lpoints.Append (tempnewpoints.Get(i)); + for (i = 1; i <= tempnewlines.Size(); i++) + llines.Append (tempnewlines.Get(i)); + for (i = 1; i <= tempdellines.Size(); i++) + dellines.Append (tempdellines.Get(i)); + for (i = 1; i <= tempelements.Size(); i++) + elements.Append (tempelements.Get(i)); + + // (*testout) << "minelerr = " << minelerr << endl; + } + + return found; +} + + + + + +} diff --git a/Netgen/libsrc/meshing/ruler2.hpp b/Netgen/libsrc/meshing/ruler2.hpp new file mode 100644 index 0000000000..3627df521e --- /dev/null +++ b/Netgen/libsrc/meshing/ruler2.hpp @@ -0,0 +1,149 @@ +#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<Point2d> transfreezone; + + /// + ARRAY<int> dellines; + /// + ARRAY<Element2d> elements; + /// + ARRAY<threefloat> tolerances, linetolerances; + /// + ARRAY<threeint> orientations; + /// + DenseMatrix oldutonewu, oldutofreearea, oldutofreearealimit; + /// + 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); } + + /// + void GetFreeZone (ARRAY<Point2d> & afreearea); + /// + float CalcPointDist (int pi, const Point2d & p) const; + /// + float CalcLineError (int li, const Vec2d & v) const; + + /// + void SetFreeZoneTransformation (const Vector & u, int tolclass); + /// + int IsInFreeZone (const Point2d & p) const + { + if (p.X() < fzminx || p.X() > fzmaxx || + p.Y() < fzminy || p.Y() > fzmaxy) return 0; + return IsInFreeZone2 (p); + } + /// + int IsInFreeZone2 (const Point2d & p) const; + /// + 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/Netgen/libsrc/meshing/ruler3.cpp b/Netgen/libsrc/meshing/ruler3.cpp new file mode 100644 index 0000000000..0d6c2dab1f --- /dev/null +++ b/Netgen/libsrc/meshing/ruler3.cpp @@ -0,0 +1,1177 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +// #define MARK +// #include <prof.h> + +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: 1 .. it is allowed to use pointi + ARRAY<Element2d> & 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 + ) + +{ + // const int rotsym = 3; + int i, j, k, ri, nfok, npok, incnpok, refpi, locpi, locfi, locfr; + int hi, minn, hpi; + 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 Element2d * locface = NULL; + int loktestmode; + + static ARRAY<int> pused; // point is already mapped + static ARRAY<int> fused; // face is already mapped + static ARRAY<int> pmap; // map of reference point to local point + static ARRAY<int> pfixed; // ??? + static ARRAY<int> fmapi; // face in reference is mapped to face nr ... + static ARRAY<int> fmapr; // face in reference is rotated to map + static ARRAY<Point3d> transfreezone; // transformed free-zone + static INDEX cnt = 0; + INDEX_2_HASHTABLE<int> ledges(lfaces.Size()); // edges in local environment + + static ARRAY<Point3d> tempnewpoints; + static ARRAY<Element2d> tempnewfaces; + static ARRAY<int> tempdelfaces; + static ARRAY<Element> tempelements; + static ARRAY<Box3d> triboxes; // bounding boxes of local faces + + + static ARRAY<int> pnearness; + static ARRAY<int> fnearness; + + cnt++; + + delfaces.SetSize (0); + elements.SetSize (0); + + + // determine topological distance of faces and points to + // base element + + + pnearness.SetSize (lpoints.Size()); + fnearness.SetSize (lfacesplit); + + for (i = 1; i <= pnearness.Size(); i++) + pnearness.Set(i, INT_MAX/10); + + for (j = 1; j <= lfaces.Get(1).GetNP(); j++) + pnearness.Set(lfaces.Get(1).PNum(j), 0); + + + // MARK(appl1); + do + { + ok = 1; + + for (i = 1; i <= lfacesplit; i++) + { + const Element2d & hface = lfaces.Get(i); + + minn = INT_MAX-1; + for (j = 1; j <= hface.GetNP(); j++) + { + hi = pnearness.Get(hface.PNum(j)); + if (hi < minn) minn = hi; + } + + for (j = 1; j <= hface.GetNP(); j++) + { + hpi = hface.PNum(j); + if (pnearness.Get(hpi) > minn+1) + { + ok = 0; + pnearness.Set(hpi, 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 (edge.I1() > pnearness.Size() || + edge.I2() > pnearness.Size() || + edge.I1() < 1 || + edge.I2() < 1) + { + cerr << "pair out of range" << endl; + exit (1); + } + + if (pnearness.Get(edge.I1()) > + pnearness.Get(edge.I2()) + 1) + { + ; + ok = 0; + pnearness.Elem(edge.I1()) = + pnearness.Get(edge.I2()) + 1; + } + if (pnearness.Get(edge.I2()) > + pnearness.Get(edge.I1()) + 1) + { + ; + ok = 0; + pnearness.Elem(edge.I2()) = + pnearness.Get(edge.I1()) + 1; + } + } + } + while (!ok); + + + for (i = 1; i <= fnearness.Size(); i++) + { + fnearness.Set(i, 0); + for (j = 1; j <= lfaces.Get(i).GetNP(); j++) + fnearness.Elem(i) += pnearness.Get(lfaces.Get(i).PNum(j)); + } + + + // MARK(appl2); + + // find bounding boxes of faces + + triboxes.SetSize (lfaces.Size()); + for (i = 1; i <= lfaces.Size(); i++) + { + const Element2d & face = lfaces.Get(i); + triboxes.Elem(i).SetPoint (lpoints.Get(face.PNum(1))); + for (j = 2; j <= face.GetNP(); j++) + triboxes.Elem(i).AddPoint (lpoints.Get(face.PNum(j))); + } + + // MARK(appl3); + + /* + for (j = 1; j <= lfacesplit; j++) + for (k = 1; k <= lfaces.Get(j).GetNP(); k++) + { + INDEX_2 i2; + i2.I1() = lfaces.Get(j).PNumMod(k); + i2.I2() = lfaces.Get(j).PNumMod(k+1); + i2.Sort(); + ledges.Set (i2, 1); + } + */ + + for (j = 1; j <= lfacesplit; j++) + { + const Element2d & face = lfaces.Get(j); + int newp, oldp; + + newp = face.PNum(face.GetNP()); + for (k = 1; k <= face.GetNP(); k++) + { + oldp = newp; + newp = face.PNum(k); + + INDEX_2 i2(oldp, newp); + i2.Sort(); + ledges.Set (i2, 1); + } + } + + + 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; + + + // check each rule: + + // MARK(applyml); + + for (ri = 1; ri <= rules.Size(); ri++) + { + sprintf (problems.Elem(ri), ""); + + rule = rules.Get(ri); + + if (rule->GetNP(1) != lfaces.Get(1).GetNP()) + continue; + + if (rule->GetQuality() > tolerance) + { + if (testmode) + sprintf (problems.Elem(ri), "Quality not ok"); + continue; + } + + if (testmode) + sprintf (problems.Elem(ri), "no mapping found"); + + loktestmode = testmode || rule->TestFlag ('t'); + /* + if (tolerance > 8) + loktestmode = 1; + */ + + if (loktestmode) + (*testout) << "Rule " << ri << " = " << rule->Name() << endl; + + pmap.SetSize (rule->GetNP()); + fmapi.SetSize (rule->GetNF()); + fmapr.SetSize (rule->GetNF()); + + for (i = 1; i <= lfaces.Size(); i++) + fused.Set (i, 0); + for (i = 1; i <= lpoints.Size(); i++) + pused.Set (i, 0); + for (i = 1; i <= pmap.Size(); i++) + pmap.Set(i, 0); + for (i = 1; i <= fmapi.Size(); i++) + fmapi.Set(i, 0); + for (i = 1; i <= fmapr.Size(); i++) + fmapr.Set(i, rule->GetNP(i)); + + fused.Set (1, 1); + + fmapi.Set (1, 1); + fmapr.Set (1, rotind1); + + + for (j = 1; j <= lfaces.Get(1).GetNP(); j++) + { + locpi = lfaces.Get(1).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; + 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) + 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 + + { + + // 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) || !allowpoint.Get(locpi) || + pnearness.Get(locpi) > rule->GetPNearness(npok)) + { + ok = 0; + } + else + { + const Point3d & lp = lpoints.Get(locpi); + const Point3d & rp = rule->GetPoint(npok); + + if ( Dist2 (lp, rp) * rule->PointDistFactor(npok) > minerr) + ok = 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 + + { + + // 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++) + { + int i1, i2; + i1 = pmap.Get(rule->GetEdge(i).i1); + i2 = pmap.Get(rule->GetEdge(i).i2); + + INDEX_2 in2(i1, 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++) + { + int i1, i2; + i1 = pmap.Get(el.PNum(j)); + i2 = pmap.Get(el.PNum(j+3)); + + INDEX_2 in2(i1, i2); + 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.Set (3*i-2, lp.X()-rp.X()); + oldu.Set (3*i-1, lp.Y()-rp.Y()); + oldu.Set (3*i , lp.Z()-rp.Z()); + + allp.Set (3*i-2, lp.X()); + allp.Set (3*i-1, lp.Y()); + allp.Set (3*i , 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.Set (3*i-2, rp.X() + newu.Get(3*i-2 - idiff)); + allp.Set (3*i-1, rp.Y() + newu.Get(3*i-1 - idiff)); + allp.Set (3*i , rp.Z() + newu.Get(3*i - 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 Element2d & 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); + } + + + // MARK(m2); + // 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.Elem (3 * (i-oldnp) - 2); + np.Y() += newu.Elem (3 * (i-oldnp) - 1); + np.Z() += newu.Elem (3 * (i-oldnp)); + + pmap.Elem(i) = lpoints.Append (np); + } + + // Set new Faces: + + for (i = rule->GetNOldF() + 1; i <= rule->GetNF(); i++) + if (!fmapi.Get(i)) + { + Element2d 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) + { + if (loktestmode) + { + sprintf (problems.Elem(ri), "Orientation wrong"); + (*testout) << "Orientation wrong" << 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 (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; + } + + // (*testout) << "end" << endl; + + // if successfull, reload best choice + + if (found) + { + +#ifdef debug + // if face in advancing front ??? + for (i = 1; i <= tempnewfaces.Size(); i++) + { + hc = 1; + for (k = 1; k <= lfaces.Size() && hc; k++) + for (j = 1; j <= 3 && hc; j++) + if (tempnewfaces.Elem(i).PNumMod(j ) == lfaces.Get(k).PNum(1) && + tempnewfaces.Elem(i).PNumMod(j+1) == lfaces.Get(k).PNum(3) && + tempnewfaces.Elem(i).PNumMod(j+2) == lfaces.Get(k).PNum(2)) + { + tempdelfaces.Append(k); + tempnewfaces.Elem(i).PNum(1) = 0; + hc = 0; + cerr << "Ruler-reload necessary" << endl; + } + } +#endif + + 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; + return found; +} +} diff --git a/Netgen/libsrc/meshing/ruler3.hpp b/Netgen/libsrc/meshing/ruler3.hpp new file mode 100644 index 0000000000..483d83ed4e --- /dev/null +++ b/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/Netgen/libsrc/meshing/secondorder.cpp b/Netgen/libsrc/meshing/secondorder.cpp new file mode 100644 index 0000000000..120ff024f1 --- /dev/null +++ b/Netgen/libsrc/meshing/secondorder.cpp @@ -0,0 +1,454 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + + + + Refinement :: Refinement () + { + ; + } + + Refinement :: ~Refinement () + { + ; + } + + void Refinement :: MakeSecondOrder (Mesh & mesh) + { + int i, j; + + INDEX_2_HASHTABLE<int> between(mesh.GetNP() + 5); + + int nseg, nse, ne; + + + nseg = mesh.GetNSeg(); + for (i = 1; i <= nseg; i++) + { + Segment & el = mesh.LineSegment(i); + + INDEX_2 i2 (el.p1, el.p2); + i2.Sort(); + + int pnew; + if (between.Used(i2)) + pnew = between.Get(i2); + else + { + Point3d pb; + EdgePointGeomInfo ngi; + PointBetween (mesh.Point (el.p1), + mesh.Point (el.p2), 0.5, + el.surfnr1, el.surfnr2, + el.epgeominfo[0], el.epgeominfo[1], + pb, ngi); + + pnew = mesh.AddPoint (pb); + between.Set (i2, pnew); + } + el.pmid = pnew; + } + + // refine surface elements + nse = mesh.GetNSE(); + for (i = 1; i <= nse; i++) + { + int j; + const Element2d & el = mesh.SurfaceElement(i); + + int onp = el.GetNP(); + + Element2d newel; + newel.SetIndex (el.GetIndex()); + + static int betw_trig[3][3] = + { { 2, 3, 4 }, + { 1, 3, 5 }, + { 1, 2, 6 } }; + static int betw_quad6[2][3] = + { { 1, 2, 5 }, + { 4, 3, 6 } }; + int (*betw)[3]; + + switch (el.GetType()) + { + case TRIG: + case TRIG6: + { + betw = betw_trig; + newel.SetType (TRIG6); + break; + } + case QUAD: + case QUAD6: + case QUAD8: + { + betw = betw_quad6; + newel.SetType (QUAD6); + break; + } + default: + PrintSysError ("Unhandled element in secondorder:", int(el.GetType())); + } + + for (j = 1; j <= onp; j++) + newel.PNum(j) = el.PNum(j); + + int nnp = newel.GetNP(); + for (j = 0; j < nnp-onp; j++) + { + int pi1 = newel.PNum(betw[j][0]); + int pi2 = newel.PNum(betw[j][1]); + + INDEX_2 i2 (pi1, pi2); + i2.Sort(); + + if (between.Used(i2)) + newel.PNum(onp+1+j) = between.Get(i2); + else + { + Point3d pb; + PointGeomInfo newgi; + 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, newgi); + + newel.PNum(onp+1+j) = mesh.AddPoint (pb); + between.Set (i2, newel.PNum(onp+1+j)); + } + } + + mesh.SurfaceElement(i) = newel; + } + + + + + // refine volume elements + ne = mesh.GetNE(); + for (i = 1; i <= ne; i++) + { + int j; + const Element & el = mesh.VolumeElement(i); + + if (el.GetType() != TET && el.GetType() != PRISM) + continue; + + int onp = el.GetNP(); + + Element newel; + newel.SetIndex (el.GetIndex()); + + static int betw_tet[6][3] = + { { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 3, 8 }, + { 2, 4, 9 }, + { 3, 4, 10 } }; + static int betw_prism[6][3] = + { + { 1, 3, 7 }, + { 1, 2, 8 }, + { 2, 3, 9 }, + { 4, 6, 10 }, + { 4, 5, 11 }, + { 5, 6, 12 }, + }; + int (*betw)[3]; + + switch (el.GetType()) + { + case TET: + case TET10: + { + betw = betw_tet; + newel.SetType (TET10); + break; + } + case PRISM: + case PRISM12: + { + betw = betw_prism; + newel.SetType (PRISM12); + break; + } + default: + PrintSysError ("MakeSecondOrder, illegal vol type ", el.GetType()); + } + + + for (j = 1; j <= onp; j++) + newel.PNum(j) = el.PNum(j); + int nnp = newel.GetNP(); + + for (j = 0; j < nnp-onp; j++) + { + INDEX_2 i2(newel.PNum(betw[j][0]), + newel.PNum(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 (i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++) + { + ARRAY<int> identmap; + mesh.GetIdentifications().GetMap (i, identmap); + + for (j = 1; j <= between.GetNBags(); j++) + for (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 (i = oldsize+1; i <= mesh.GetNP(); i++) + { + mesh.mlbetweennodes.Elem(i).I1() = 0; + mesh.mlbetweennodes.Elem(i).I2() = 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; + } + + mesh.ComputeNVertices(); + + // 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 (i = 1; i <= np; i++) + parents.Elem(i) = INDEX_2(0,0); + + for (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 (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 (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<Point3d> should(np); + ARRAY<Point3d> can(np); + + for (i = 1; i <= np; i++) + { + should.Elem(i) = can.Elem(i) = mesh.Point(i); + } + + for (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 (i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & sel = mesh.SurfaceElement(i); + for (j = 1; j <= sel.GetNP(); j++) + boundp.Set(sel.PNum(j)); + } + + + (*testout) << "bpoints:" << endl; + for (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 (i = 1; i <= np; i++) + if (boundp.Test(i)) + { + for (j = 1; j <= 3; j++) + mesh.Point(i).X(j) = + lam * should.Get(i).X(j) + + (1-lam) * can.Get(i).X(j); + } + else + mesh.Point(i) = can.Get(i); + + // (*testout) << "bad els: " << endl; + wrongels = 0; + for (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(); + mesh.ImproveMeshJacobian (OPT_WORSTCASE); + + facok = factry; + for (i = 1; i <= np; i++) + can.Elem(i) = mesh.Point(i); + } + } + + + + for (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/Netgen/libsrc/meshing/smoothing2.cpp b/Netgen/libsrc/meshing/smoothing2.cpp new file mode 100644 index 0000000000..32e44b256d --- /dev/null +++ b/Netgen/libsrc/meshing/smoothing2.cpp @@ -0,0 +1,790 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#include <opti.hpp> + +namespace netgen +{ + +static const MeshOptimize2d * meshthis; + + + + +inline void CalcTriangleBadness (double x2, double x3, double y3, double metricweight, + double h, double & badness, double & g1x, double & g1y) +{ + // badness = sqrt(3.0) /36 * circumference^2 / area - 1 + // p1 = (0, 0), p2 = (x2, 0), p3 = (x3, y3); + + Vec2d v23; + double l12, l13, l23, cir, area; + static const double c = sqrt(3.0) / 36; + double c1, c2, c3, c4; + + v23.X() = x3 - x2; + v23.Y() = y3; + + l12 = x2; + l13 = sqrt (x3*x3 + y3*y3); + l23 = v23.Length(); + + cir = l12 + l13 + l23; + area = 0.5 * x2 * y3; + + if (area <= 1e-24 * cir * cir) + { + g1x = 0; + g1y = 0; + badness = 1e10; + return; + } + + badness = c * cir * cir / area - 1; + + c1 = 2 * c * cir / area; + c2 = 0.5 * c * cir * cir / (area * area); + + g1x = c1 * ( - 1 - x3 / l13) - c2 * (-v23.Y()); + g1y = c1 * ( - y3 / l13) - c2 * ( v23.X()); + + // metricweight = 0.1; + if (metricweight > 0) + { + // area = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1); + // add: metricweight * (area / h^2 + h^2 / area - 2) + + const double area = x2 * y3; + const double dareax1 = -y3; + const double dareay1 = x3 - x2; + + const double areahh = area / (h * h); + const double fac = metricweight * (areahh - 1 / areahh) / area; + + badness += metricweight * (areahh + 1 / areahh - 2); + g1x += fac * dareax1; + g1y += fac * dareay1; + + /* + // add: metricweight * (l1^2/h^2 + l2^2/h^2 + l3^2/h2 + h^2/l1^2 + h^2/l2^2 + h^2/l3^2 - 6) + double h2 = h*h; + double l1 = x2*x2; + double l2 = x3*x3+y3*y3; + double l3 = (x2-x3)*(x2-x3)+y3*y3; + double dl1dx = 2*(-x2); + double dl1dy = 0; + double dl2dx = -2*x3; + double dl2dy = -2*y3; + + badness += (l1/h2 + l2/h2 + l3/h2 +h2/l1 + h2/l2 + h2/l3-6) * metricweight; + + g1x += metricweight * (dl1dx/h2-h2/(l1*l1)*dl1dx + dl2dx/h2-h2/(l2*l2)*dl2dx); + g1y += metricweight * (dl1dy/h2-h2/(l1*l1)*dl1dy + dl2dy/h2-h2/(l2*l2)*dl2dy); + */ + } +} + + + double CalcTriangleBadness (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + double metricweight, + double h) + { + double badness; + double g1x, g1y; + + Vec3d e1 (p1, p2); + Vec3d e2 (p1, p3); + + double e1l = e1.Length() + 1e-24; + e1 /= e1l; + double e1e2 = (e1 * e2); + e2.Add (-e1e2, e1); + double e2l = e2.Length(); + + CalcTriangleBadness ( e1l, e1e2, e2l, + metricweight, h, badness, g1x, g1y); + return badness; +} + + +double CalcTriangleBadness (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + const Vec3d & n, + double metricweight, + double h) +{ + double badness; + double g1x, g1y; + + Vec3d v1 (p1, p2); + Vec3d v2 (p1, p3); + + Vec3d e1 = v1; + Vec3d e2 = v2; + + e1 -= (e1 * n) * n; + e1 /= (e1.Length() + 1e-12); + e2 = Cross (n, e1); + + CalcTriangleBadness ( (e1 * v1), (e1 * v2), (e2 * v2), + metricweight, h, badness, g1x, g1y); + return badness; +} + + + + +static Point3d sp1; +static PointGeomInfo gi1; +static Vec3d n, t1, t2; +static ARRAY<SurfaceElementIndex> locelements(0); +static ARRAY<int> locrots(0); +static ARRAY<double> lochs(0); +// static int locerr2; +static double locmetricweight = 0; +static double loch; +static int surfi, surfi2; +static int uselocalh; + + +class Opti2SurfaceMinFunction : public MinFunction +{ + const Mesh & mesh; +public: + Opti2SurfaceMinFunction (const Mesh & amesh) + : mesh(amesh) + { } ; + virtual double FuncGrad (const Vector & x, Vector & g) 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 +{ + int j, roti; + Vec3d n, vgrad; + Point3d pp1; + Vec2d g1; + double badness, hbadness; + + vgrad = 0; + badness = 0; + + + meshthis -> GetNormalVector (surfi, sp1, gi1, n); + + pp1 = sp1; + pp1.Add2 (x.Get(1), t1, x.Get(2), t2); + + // meshthis -> ProjectPoint (surfi, pp1); + // meshthis -> GetNormalVector (surfi, pp1, n); + + + for (j = 0; j < locelements.Size(); j++) + { + roti = locrots[j]; + const Element2d & bel = mesh[locelements[j]]; + + Vec3d e1(pp1, mesh[bel.PNumMod(roti + 1)]); + Vec3d e2(pp1, mesh[bel.PNumMod(roti + 2)]); + + if (uselocalh) loch = lochs[j]; + + double e1l = e1.Length(); + if (Determinant(e1, e2, n) > 1e-8 * e1l * e2.Length()) + { + e1 /= e1l; + double e1e2 = e1 * e2; + e2.Add (-e1e2, e1); + double e2l = e2.Length(); + + CalcTriangleBadness ( e1l, e1e2, e2l, locmetricweight, loch, + hbadness, g1.X(), g1.Y()); + + badness += hbadness; + vgrad.Add2 (g1.X(), e1, g1.Y() / e2l, e2); + } + else + badness += 1e8; + } + + vgrad.Add (-(vgrad * n), n); + + grad.Elem(1) = vgrad * t1; + grad.Elem(2) = vgrad * t2; + return badness; +} + + +class Opti2EdgeMinFunction : public MinFunction +{ + const Mesh & mesh; +public: + Opti2EdgeMinFunction (const Mesh & amesh) + : mesh(amesh) { } ; + + 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; + Vec3d n1, n2, v1, v2, e1, e2, vgrad; + Point3d pp1; + Vec2d g1; + double badness, hbadness; + + vgrad.X() = 0; + vgrad.Y() = 0; + vgrad.Z() = 0; + badness = 0; + + pp1 = sp1 + x.Get(1) * t1; + meshthis -> ProjectPoint2 (surfi, surfi2, pp1); + + for (j = 0; j < locelements.Size(); j++) + { + rot = locrots[j]; + const Element2d & bel = mesh[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 (uselocalh) loch = lochs[j]; + CalcTriangleBadness ( (e1 * v1), (e1 * v2), (e2 * v2), locmetricweight, loch, + hbadness, g1.X(), g1.Y()); + + badness += hbadness; + + vgrad.X() += g1.X() * e1.X() + g1.Y() * e2.X(); + vgrad.Y() += g1.X() * e1.Y() + g1.Y() * e2.Y(); + vgrad.Z() += g1.X() * e1.Z() + g1.Y() * e2.Z(); + } + + meshthis -> GetNormalVector (surfi, pp1, n1); + meshthis -> GetNormalVector (surfi2, pp1, n2); + + v1 = Cross (n1, n2); + v1 /= v1.Length(); + + grad.Elem(1) = (vgrad * v1) * (t1 * v1); + + return badness; +} + + + + +class Opti2SurfaceMinFunctionJacobian : public MinFunction +{ + const Mesh & mesh; +public: + Opti2SurfaceMinFunctionJacobian (const Mesh & amesh) + : mesh(amesh) + { } ; + virtual double FuncGrad (const Vector & x, Vector & g) 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 j, k, lpi, gpi; + Vec3d n, vgrad; + Point3d pp1; + Vec2d g1, vdir; + double badness, hbadness, hbad, hderiv; + + vgrad = 0; + badness = 0; + + meshthis -> GetNormalVector (surfi, sp1, gi1, n); + + pp1 = sp1; + pp1.Add2 (x.Get(1), t1, x.Get(2), t2); + + // meshthis -> ProjectPoint (surfi, pp1); + // meshthis -> GetNormalVector (surfi, pp1, n); + + static ARRAY<Point2d> pts2d; + pts2d.SetSize(mesh.GetNP()); + + grad = 0; + + for (j = 1; j <= locelements.Size(); j++) + { + lpi = locrots.Get(j); + const Element2d & bel = + mesh[locelements.Get(j)]; + + gpi = bel.PNum(lpi); + + for (k = 1; k <= bel.GetNP(); k++) + { + PointIndex pi = bel.PNum(k); + pts2d.Elem(pi) = Point2d (t1 * (mesh.Point(pi) - sp1), + t2 * (mesh.Point(pi) - sp1)); + } + pts2d.Elem(gpi) = Point2d (x.Get(1), x.Get(2)); + + + for (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.Elem(k) += hderiv; + if (k == 1) + badness += hbad; + } + + + /* + Vec3d e1(pp1, mesh.Point(bel.PNumMod(lpi + 1))); + Vec3d e2(pp1, mesh.Point(bel.PNumMod(lpi + 2))); + + if (uselocalh) + loch = lochs.Get(j); + + double e1l = e1.Length(); + if (Determinant(e1, e2, n) > 1e-8 * e1l * e2.Length()) + { + e1 /= e1l; + double e1e2 = e1 * e2; + e2.Add (-e1e2, e1); + double e2l = e2.Length(); + + CalcTriangleBadness ( e1l, e1e2, e2l, locmetricweight, loch, + hbadness, g1.X(), g1.Y()); + + badness += hbadness; + vgrad.Add2 (g1.X(), e1, g1.Y() / e2l, e2); + } + else + badness += 1e8; + */ + } + + + /* + vgrad.Add (-(vgrad * n), n); + + grad.Elem(1) = vgrad * t1; + grad.Elem(2) = vgrad * t2; + */ + return badness; + + /* + + // from 3d: + + int j, k; + int lpi; + double badness = 0, hbad; + + Point3d hp = points.Elem(actpind); + points.Elem(actpind) = hp + Vec3d (x.Get(1), x.Get(2), x.Get(3)); + + double 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; + + for (k = 1; k <= 3; k++) + { + vdir = Vec3d(0,0,0); + vdir.X(k) = 1; + + hbad = elements.Get(eli). + CalcJacobianBadnessDirDeriv (points, lpi, vdir, hderiv); + g.Elem(k) += hderiv; + if (k == 1) + badness += hbad; + } + } + + points.Elem(actpind) = hp; + + return badness; + + */ + +} + + + + + + + +MeshOptimize2d dummy; + +MeshOptimize2d :: MeshOptimize2d () +{ + SetFaceIndex (0); + SetImproveEdges (0); + SetMetricWeight (0); + SetWriteStatus (1); +} + + +void MeshOptimize2d :: SelectSurfaceOfPoint (const Point3d & p, + const PointGeomInfo & gi) +{ + ; +} + +void MeshOptimize2d :: ImproveMesh (Mesh & mesh) +{ + if (!faceindex) + { + PrintMessage (3, "Smoothing"); + + for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) + { + ImproveMesh (mesh); + if (multithread.terminate) + throw NgException ("Meshing stopped"); + } + faceindex = 0; + return; + } + + CheckMeshApproximation (mesh); + + int i, j, k, surfi3; + 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; + int moveisok; + + PointGeomInfo ngi; + Point3d origp; + + Vec3d n1, n2; + Vector x(2), xedge(1); + + ARRAY<Point3d, PointIndex::BASE> savepoints(mesh.GetNP()); + uselocalh = mparam.uselocalh; + + 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]); + } + + loch = mparam.maxh; + locmetricweight = metricweight; + meshthis = this; + + Opti2SurfaceMinFunction surfminf(mesh); + Opti2EdgeMinFunction edgeminf(mesh); + Opti2SurfaceMinFunctionJacobian surfminfj(mesh); + + OptiParameters par; + par.maxit_linsearch = 8; + par.maxit_bfgs = 5; + + /* + 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; + } + int cnt = 0; + + for (PointIndex pi = PointIndex::BASE; + pi < mesh.GetNP()+PointIndex::BASE; pi++) + + if (mesh.PointType(pi) == SURFACEPOINT) + { + if (multithread.terminate) + throw NgException ("Meshing stopped"); + + cnt++; + if (cnt % modplot == 0 && writestatus) + { + printeddot = 1; + PrintDot (plotchar); + } + + if (elementsonpoint[pi].Size() == 0) + continue; + + sp1 = mesh[pi]; + + Element2d & hel = mesh[elementsonpoint[pi][0]]; + + int hpi = 0; + for (j = 1; j <= hel.GetNP(); j++) + if (hel.PNum(j) == pi) + { + hpi = j; + break; + } + + gi1 = hel.GeomInfoPi(hpi); + SelectSurfaceOfPoint (sp1, gi1); + + locelements.SetSize(0); + locrots.SetSize (0); + lochs.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; + } + + if (uselocalh) + { + Point3d pmid = Center (mesh[bel[0]], mesh[bel[1]], mesh[bel[2]]); + lochs.Append (mesh.GetH(pmid)); + } + } + + + GetNormalVector (surfi, sp1, gi1, n); + n.GetNormal (t1); + t2 = Cross (n, t1); + + // save points, and project to tangential plane + for (j = 0; j < locelements.Size(); j++) + { + const Element2d & el = mesh[locelements[j]]; + for (k = 0; k < el.GetNP(); k++) + savepoints[el[k]] = mesh[el[k]]; + } + + for (j = 0; j < locelements.Size(); j++) + { + const Element2d & el = mesh[locelements[j]]; + for (k = 0; k < el.GetNP(); k++) + { + PointIndex hpi = el[k]; + double lam = n * (mesh[hpi] - sp1); + mesh[hpi] -= lam * n; + } + } + + x = 0; + + if (mixed) + BFGS (x, surfminfj, par, 1e-6); + else + BFGS (x, surfminf, par, 1e-6); + + origp = mesh[pi]; + loci = 1; + fact = 1; + moveisok = 0; + + // restore other points + for (j = 0; j < locelements.Size(); j++) + { + const Element2d & el = mesh[locelements[j]]; + for (k = 0; k < el.GetNP(); k++) + { + PointIndex hpi = el[k]; + if (hpi != pi) mesh[hpi] = savepoints[hpi]; + } + } + + + //optimizer loop (if not 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; + fact = fact/2.; + ProjectPoint (surfi, mesh[pi]); + + moveisok = CalcPointGeomInfo(surfi, ngi, mesh[pi]); + // point lies on same chart in stlsurface + + if (moveisok) + { + for (j = 0; j < locelements.Size(); j++) + mesh[locelements[j]].GeomInfoPi(locrots[j]) = ngi; + } + else + { + mesh[pi] = origp; + } + + } + // (*testout) << " new: " << mesh.Point(i) << endl; + } + + if (printeddot) + PrintDot ('\n'); + + CheckMeshApproximation (mesh); + mesh.SetNextTimeStamp(); +} + +void MeshOptimize2d :: GetNormalVector(INDEX /* surfind */, const Point3d & p, Vec3d & nv) const +{ + nv = Vec3d (0, 0, 1); +} + +void MeshOptimize2d :: GetNormalVector(INDEX surfind, const Point3d & p, PointGeomInfo & gi, Vec3d & n) const +{ + GetNormalVector (surfind, p, n); +} + +} diff --git a/Netgen/libsrc/meshing/smoothing3.cpp b/Netgen/libsrc/meshing/smoothing3.cpp new file mode 100644 index 0000000000..6fcb2b8e70 --- /dev/null +++ b/Netgen/libsrc/meshing/smoothing3.cpp @@ -0,0 +1,1557 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#ifdef SOLIDGEOM +#include <csg.hpp> +#endif +#include <opti.hpp> + + +namespace netgen +{ + + + PointFunction1 :: PointFunction1 (Mesh::T_POINTS & apoints, + const ARRAY<INDEX_3> & afaces, + double ah) + : points(apoints), faces(afaces) + { + h = ah; + } + + + double PointFunction1 :: Func (const Vector & vp) const + { + int j; + double badness = 0; + Point3d pp(vp.Get(1), vp.Get(2), vp.Get(3)); + + for (j = 0; j < faces.Size(); j++) + { + const INDEX_3 & el = faces[j]; + + double bad = CalcTetBadness (points.Get(el.I1()), + points.Get(el.I3()), + points.Get(el.I2()), + pp, 0); + badness += bad; + } + + return badness; + } + + + + double PointFunction1 :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const + { + static Vector hx(3); + static 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 + { + static Vector hx(3); + static double eps = 1e-6; + + hx = x; + for (int i = 1; i <= 3; i++) + { + hx.Elem(i) = x.Get(i) + eps * h; + double fr = Func (hx); + hx.Elem(i) = x.Get(i) - eps * h; + double fl = Func (hx); + hx.Elem(i) = x.Get(i); + + g.Elem(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 */ + + 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 i, nf = faces.Size(); + + m.SetSize (nf, 4); + + for (i = 1; i <= nf; i++) + { + const Point3d & p1 = points.Get(faces.Get(i).I1()); + const Point3d & p2 = points.Get(faces.Get(i).I2()); + const Point3d & p3 = points.Get(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; + static Vector hv(4); + static Vector res; + res.SetSize (m.Height()); + + for (i = 1;i <= 3; i++) + hv.Elem(i) = vp.Get(i); + hv.Elem(4) = 1; + m.Mult (hv, res); + + for (i = 1; i <= res.Size(); i++) + { + if (res.Get(i) < 1e-10) + badness += 1e24; + else + badness += 1 / res.Get(i); + } + + return badness; + } + + + double CheapPointFunction1 :: FuncGrad (const Vector & x, Vector & g) const + { + static Vector hx(3); + static double eps = 1e-6; + + hx = x; + for (int i = 1; i <= 3; i++) + { + hx.Elem(i) = x.Get(i) + eps * h; + double fr = Func (hx); + hx.Elem(i) = x.Get(i) - eps * h; + double fl = Func (hx); + hx.Elem(i) = x.Get(i); + + g.Elem(i) = (fr - fl) / (2 * eps * h); + } + + return Func(x); + } + + + + + + + + + + + + + + + + /* ************* PointFunction **************************** */ + + + class PointFunction + { + public: + Mesh::T_POINTS & points; + const Mesh::T_VOLELEMENTS & elements; + TABLE<INDEX> elementsonpoint; + int actpind; + double h; + + public: + PointFunction (Mesh::T_POINTS & apoints, + const Mesh::T_VOLELEMENTS & aelements); + + virtual void SetPointIndex (int aactpind); + void SetLocalH (double ah) { h = ah; } + double GetLocalH () const { return h; } + virtual double PointFunctionValue (const Point3d & pp) const; + virtual double PointFunctionValueGrad (const Point3d & pp, Vector & grad) const; + virtual double PointFunctionValueDeriv (const Point3d & pp, const Vec3d & dir, double & deriv) const; + + int MovePointToInner (); + }; + + + PointFunction :: PointFunction (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++) + { + if (elements.Get(i).NP() == 4) + for (j = 1; j <= elements.Get(i).NP(); j++) + elementsonpoint.Add1 (elements.Get(i).PNum(j), i); + } + } + + void PointFunction :: SetPointIndex (int aactpind) + { + actpind = aactpind; + } + + double PointFunction :: PointFunctionValue (const Point3d & pp) const + { + int j; + INDEX eli; + const Element * el; + double badness; + // ARRAY<const Point3d*> p(4); + Point3d hp; + + badness = 0; + + hp = points.Elem(actpind); + points.Elem(actpind) = pp; + + for (j = 1; j <= elementsonpoint.EntrySize(actpind); j++) + { + eli = elementsonpoint.Get(actpind, j); + el = &elements.Get(eli); + badness += CalcTetBadness (points.Get(el->PNum(1)), + points.Get(el->PNum(2)), + points.Get(el->PNum(3)), + points.Get(el->PNum(4)), -1); + } + + points.Elem(actpind) = hp; + return badness; + } + + + double PointFunction :: PointFunctionValueGrad (const Point3d & pp, Vector & grad) const + { + double f, delta = h * 1e-6; + Point3d hpp; + + f = PointFunctionValue (pp); + + /* + hpp = pp; + hpp.X() = pp.X() + delta; + fr = PointFunctionValue (hpp); + hpp.X() = pp.X() - delta; + fl = PointFunctionValue (hpp); + grad.Elem(1) = (fr - fl) / (2 * delta); + + hpp = pp; + hpp.Y() = pp.Y() + delta; + fr = PointFunctionValue (hpp); + hpp.Y() = pp.Y() - delta; + fl = PointFunctionValue (hpp); + grad.Elem(2) = (fr - fl) / (2 * delta); + + hpp = pp; + hpp.Z() = pp.Z() + delta; + fr = PointFunctionValue (hpp); + hpp.Z() = pp.Z() - delta; + fl = PointFunctionValue (hpp); + grad.Elem(3) = (fr - fl) / (2 * delta); + */ + + + + // new gradient calculation + int j, k; + INDEX eli; + // double badness; + Point3d hp; + Vec3d vgradi, vgrad(0,0,0); + + // badness = 0; + + hp = points.Elem(actpind); + points.Elem(actpind) = pp; + + for (j = 1; j <= elementsonpoint.EntrySize(actpind); j++) + { + eli = elementsonpoint.Get(actpind, j); + const Element & el = elements.Get(eli); + + for (k = 1; k <= 4; k++) + if (el.PNum(k) == actpind) + { + CalcTetBadnessGrad (points.Get(el.PNum(1)), + points.Get(el.PNum(2)), + points.Get(el.PNum(3)), + points.Get(el.PNum(4)), -1, k, vgradi); + vgrad += vgradi; + } + } + points.Elem(actpind) = hp; + + for (j = 1; j <= 3; j++) + grad.Elem(j) = vgrad.X(j); + + return f; + } + + + double PointFunction :: PointFunctionValueDeriv (const Point3d & pp, const Vec3d & dir, + double & deriv) const + { + double f; + Point3d hpp; + + Vec3d dirn (dir); + double ldir = dir.Length(); + + int j, k; + INDEX eli; + // double badness; + Point3d hp; + Vec3d vgradi, vgrad(0,0,0); + + // badness = 0; + + hp = points.Elem(actpind); + points.Elem(actpind) = pp; + f = 0; + + for (j = 1; j <= elementsonpoint.EntrySize(actpind); j++) + { + eli = elementsonpoint.Get(actpind, j); + const Element & el = elements.Get(eli); + + for (k = 1; k <= 4; k++) + if (el.PNum(k) == actpind) + { + f += CalcTetBadnessGrad (points.Get(el.PNum(1)), + points.Get(el.PNum(2)), + points.Get(el.PNum(3)), + points.Get(el.PNum(4)), -1, k, vgradi); + + vgrad += vgradi; + } + } + + points.Elem(actpind) = hp; + deriv = dir * vgrad; + return f; + } + + int PointFunction :: MovePointToInner () + { + int j, k; + + // try point movement + ARRAY<Element2d> faces; + + for (j = 1; j <= elementsonpoint.EntrySize(actpind); j++) + { + const Element & el = + elements.Get(elementsonpoint.Get (actpind, j)); + + for (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.Elem(actpind) = hp; + } + else + cout << "no inner point found" << endl; + + + + return hi; + } + + + + + + + class CheapPointFunction : public PointFunction + { + DenseMatrix m; + public: + CheapPointFunction (Mesh::T_POINTS & apoints, + const Mesh::T_VOLELEMENTS & aelements); + virtual void SetPointIndex (int aactpind); + virtual double PointFunctionValue (const Point3d & pp) const; + virtual double PointFunctionValueGrad (const Point3d & pp, Vector & grad) const; + }; + + + CheapPointFunction :: CheapPointFunction (Mesh::T_POINTS & apoints, + const Mesh::T_VOLELEMENTS & aelements) + : PointFunction (apoints, aelements) + { + ; + } + + + void CheapPointFunction :: SetPointIndex (int aactpind) + { + actpind = aactpind; + + int n = elementsonpoint.EntrySize(actpind); + int i, j; + int pi1, pi2, pi3; + + m.SetSize (n, 4); + + for (i = 1; i <= n; i++) + { + pi1 = 0; + pi2 = 0; + pi3 = 0; + + const Element & el = elements.Get (elementsonpoint.Get(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.Get(pi1); + Vec3d v1 (p1, points.Get(pi2)); + Vec3d v2 (p1, points.Get(pi3)); + Vec3d n; + Cross (v1, v2, n); + n /= n.Length(); + + Vec3d v (p1, points.Get(actpind)); + double c = v * n; + + if (c < 0) + n *= -1; + + // n is inner normal + + 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 CheapPointFunction :: PointFunctionValue (const Point3d & pp) const + { + static Vector p4(4); + static Vector di; + int n = m.Height(); + + p4.Elem(1) = pp.X(); + p4.Elem(2) = pp.Y(); + p4.Elem(3) = pp.Z(); + p4.Elem(4) = 1; + + di.SetSize (n); + m.Mult (p4, di); + + double sum = 0; + for (int i = 1; i <= n; i++) + { + if (di.Get(i) > 0) + sum += 1 / di.Get(i); + else + return 1e16; + } + return sum; + } + + + + + double CheapPointFunction :: PointFunctionValueGrad (const Point3d & pp, Vector & grad) const + { + static Vector p4(4); + static Vector di; + + grad.SetSize (3); + int n = m.Height(); + + p4.Elem(1) = pp.X(); + p4.Elem(2) = pp.Y(); + p4.Elem(3) = pp.Z(); + p4.Elem(4) = 1; + + di.SetSize (n); + m.Mult (p4, di); + + double sum = 0; + grad = 0; + for (int i = 1; i <= n; i++) + { + if (di.Get(i) > 0) + { + double idi = 1 / di.Get(i); + sum += idi; + grad.Elem(1) -= idi * idi * m.Get(i, 1); + grad.Elem(2) -= idi * idi * m.Get(i, 2); + grad.Elem(3) -= idi * idi * m.Get(i, 3); + } + else + { + return 1e16; + } + } + return sum; + } + + + + + + + + + class Opti3FreeMinFunction : public MinFunction + { + const PointFunction & pf; + Point3d sp1; + + public: + Opti3FreeMinFunction (const PointFunction & apf); + void SetPoint (const Point3d & 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 + { + Point3d pp; + pp.X() = sp1.X() + x.Get(1); + pp.Y() = sp1.Y() + x.Get(2); + pp.Z() = sp1.Z() + x.Get(3); + + return pf.PointFunctionValue (pp); + } + + double Opti3FreeMinFunction :: FuncGrad (const Vector & x, Vector & grad) const + { + Point3d pp; + pp.X() = sp1.X() + x.Get(1); + pp.Y() = sp1.Y() + x.Get(2); + pp.Z() = sp1.Z() + x.Get(3); + + return pf.PointFunctionValueGrad (pp, grad); + } + + double Opti3FreeMinFunction :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const + { + Point3d pp; + pp.X() = sp1.X() + x.Get(1); + pp.Y() = sp1.Y() + x.Get(2); + pp.Z() = sp1.Z() + x.Get(3); + + Vec3d vdir; + vdir.X() = dir.Get(1); + vdir.Y() = dir.Get(2); + vdir.Z() = dir.Get(3); + + 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(); + int i, j; + + static Vector hx; + hx.SetSize(n); + + double eps = 1e-8; + double f, f11, f12, f21, f22; + + f = Func(x); + + + for (i = 1; i <= n; i++) + { + for (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.Elem(i) = x.Get(i) + eps; + f11 = Func(hx); + hx.Elem(i) = x.Get(i) - 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; + double badness; + static Vector freegrad(3); + + 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> 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; + static Vector freegrad(3); + + 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 CalcBad (const Mesh::T_POINTS & points, const Element & elem, + double h) +{ + if (elem.GetType() == TET) + return CalcTetBadness (points[elem.PNum(1)], + points[elem.PNum(2)], + points[elem.PNum(3)], + points[elem.PNum(4)], h); + return 0; +} + + +extern double teterrpow; +double CalcTotalBad (const Mesh::T_POINTS & points, + const Mesh::T_VOLELEMENTS & elements) +{ + int i; + double sum = 0; + double elbad; + + tets_in_qualclass.SetSize(20); + for (i = 1; i <= 20; i++) + tets_in_qualclass.Elem(i) = 0; + + + for (i = 1; i <= elements.Size(); i++) + { + elbad = pow (CalcBad (points, elements.Get(i), 0), 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; + int actpind; + +public: + JacobianPointFunction (Mesh::T_POINTS & apoints, + const Mesh::T_VOLELEMENTS & aelements); + + virtual void SetPointIndex (int 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); + } +} + +void JacobianPointFunction :: SetPointIndex (int aactpind) +{ + actpind = aactpind; +} + + +double JacobianPointFunction :: Func (const Vector & v) const +{ + int j; + double badness = 0; + + Point3d hp = points.Elem(actpind); + points.Elem(actpind) = hp + Vec3d (v.Get(1), v.Get(2), v.Get(3)); + + 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; + + Point3d hp = points.Elem(actpind); + points.Elem(actpind) = hp + Vec3d (x.Get(1), x.Get(2), x.Get(3)); + + double 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; + + for (k = 1; k <= 3; k++) + { + vdir = Vec3d(0,0,0); + vdir.X(k) = 1; + + hbad = elements.Get(eli). + CalcJacobianBadnessDirDeriv (points, lpi, vdir, hderiv); + g.Elem(k) += hderiv; + if (k == 1) + badness += hbad; + } + } + + 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; + + Point3d hp = points.Elem(actpind); + points.Elem(actpind) = hp + Vec3d (x.Get(1), x.Get(2), x.Get(3)); + + double hderiv; + deriv = 0; + Vec3d vdir(dir.Get(1), dir.Get(2), dir.Get(3)); + + 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; + + /* + (*testout) << "bad1 = " << badness << " der = " << deriv << endl; + + + + static Vector hx(3); + static double eps = 1e-6; + + double dirlen = dir.L2Norm(); + if (dirlen < 1e-14) + { + deriv = 0; + return Func(x); + } + + hx.Set(1, x); + hx.Add(eps / dirlen, dir); + double fr = Func (hx); + hx.Set(1, x); + hx.Add(-eps / dirlen, dir); + double fl = Func (hx); + + deriv = (fr - fl) / (2 * eps) * dirlen; + + + (*testout) << "bad2 = " << Func(x) << " der = " << deriv << endl; + + + return Func(x); + */ +} + + + + + + + + + + +#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; + } + + 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).precision(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; + + + + 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 ('+'); + + // (*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 (OPTIMIZEGOAL goal) +{ + int typ = 1; + int i, j; + + (*testout) << "Improve Mesh2" << "\n"; + PrintMessage (3, "ImproveMesh2"); + + int np = GetNP(); + int ne = GetNE(); + + + ARRAY<double> perrs(np); + for (i = 1; i <= np; i++) + perrs.Elem(i) = 1; + + double bad1 = 0; + double badmax = 0; + + if (goal == OPT_QUALITY) + { + for (i = 1; i <= ne; i++) + { + const Element & el = VolumeElement(i); + if (el.GetType() != TET) + continue; + + double hbad = CalcBad (points, el, 0); + for (j = 1; j <= 4; j++) + perrs.Elem(el.PNum(j)) += hbad; + + bad1 += hbad; + } + + for (i = 1; i <= np; i++) + if (perrs.Get(i) > badmax) + badmax = perrs.Get(i); + badmax = 0; + } + + if (goal == OPT_QUALITY) + { + bad1 = CalcTotalBad (points, volelements); + (*testout) << "Total badness = " << bad1 << endl; + PrintMessage (5, "Total badness = ", bad1); + } + + Vector x(3); + + (*testout).precision(8); + + int uselocalh = mparam.uselocalh; + + + PointFunction * pf; + + if (typ == 1) + pf = new PointFunction(points, volelements); + else + pf = new CheapPointFunction(points, volelements); + + // pf->SetLocalH (h); + + Opti3FreeMinFunction freeminf(*pf); + + OptiParameters par; + par.maxit_linsearch = 20; + par.maxit_bfgs = 20; + + + char * savetask = multithread.task; + multithread.task = "Smooth Mesh"; + + for (i = 1; i <= points.Size(); i++) + if (PointType(i) == INNERPOINT && perrs.Get(i) > 0.01 * badmax) + { + 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 (uselocalh) + { + double lh = GetH(points.Get(i)); + pf->SetLocalH (lh); + par.typx = lh; + // (*mycout) << "lh = " << lh << "\n"; + } + + // if (elementsonpoint.EntrySize(i) == 0) continue; + + freeminf.SetPoint (points.Elem(i)); + pf->SetPointIndex (i); + + x = 0; + int pok; + pok = freeminf.Func (x) < 1e10; + + if (!pok) + { + pok = pf->MovePointToInner (); + + freeminf.SetPoint (points.Elem(i)); + pf->SetPointIndex (i); + } + + if (pok) + { + 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); + } + } + PrintDot ('\n'); + + + delete pf; + + multithread.task = savetask; + + if (goal == OPT_QUALITY) + { + bad1 = CalcTotalBad (points, volelements); + (*testout) << "Total badness = " << bad1 << endl; + PrintMessage (5, "Total badness = ", bad1); + } +} + + + + +// Improve Condition number of Jacobian, any elements +void Mesh :: ImproveMeshJacobian (OPTIMIZEGOAL goal) +{ + 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); + + + 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)); + } + + + char * savetask = multithread.task; + multithread.task = "Smooth Mesh Jacobian"; + + for (i = 1; i <= points.Size(); i++) + if (PointType(i) == INNERPOINT) + { + + (*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 = GetH(points.Get(i)); + par.typx = lh; + + pf.SetPointIndex (i); + + x = 0; + int pok = (pf.Func (x) < 1e10); + + if (pok) + { + BFGS (x, pf, par); + + points.Elem(i).X() += x.Get(1); + points.Elem(i).Y() += x.Get(2); + points.Elem(i).Z() += x.Get(3); + } + else + { + cout << "el not ok" << endl; + } + } + PrintDot ('\n'); + + + multithread.task = savetask; +} + + + + +} diff --git a/Netgen/libsrc/meshing/specials.cpp b/Netgen/libsrc/meshing/specials.cpp new file mode 100644 index 0000000000..ae9877cc2e --- /dev/null +++ b/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(); +} + + + + +void HelmholtzMesh (Mesh & mesh) +{ + int i, j; + 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++) + { + Point3d & p = mesh.Point(i); + double rold = sqrt (sqr(p.X()) + sqr(p.Y()) + sqr(p.Z())); + if (rold < ri) continue; + + double rnew = 1 / (a * rold - b); + double fac = rnew / rold; + p.X() *= fac; + p.Y() *= fac; + p.Z() *= fac; + } +} +} diff --git a/Netgen/libsrc/meshing/specials.hpp b/Netgen/libsrc/meshing/specials.hpp new file mode 100644 index 0000000000..700ba4596b --- /dev/null +++ b/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/Netgen/libsrc/meshing/tetrarls.cpp b/Netgen/libsrc/meshing/tetrarls.cpp new file mode 100644 index 0000000000..cb28648b6a --- /dev/null +++ b/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/Netgen/libsrc/meshing/topology.cpp b/Netgen/libsrc/meshing/topology.cpp new file mode 100644 index 0000000000..9b91a464dc --- /dev/null +++ b/Netgen/libsrc/meshing/topology.cpp @@ -0,0 +1,1523 @@ +#include <mystdlib.h> + +#include "meshing.hpp" + +namespace netgen +{ + +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"); +} + +void MeshTopology :: Update() +{ + int i, j, k; + + 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(); + + PrintMessage (3, "Update mesh topology"); + + (*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> cnt(nv); + ARRAY<int> vnums; + + (*testout) << "tables deleted" << endl; + + /* + generate: + vertex to element + vertex to surface element + vertex to segment + */ + + cnt = 0; + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + int nelv = el.GetNV(); + for (j = 1; j <= nelv; j++) + cnt.Elem(el.PNum(j))++; + } + vert2element = new TABLE<int> (cnt); + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + int nelv = el.GetNV(); + for (j = 1; j <= nelv; j++) + vert2element->AddSave (el.PNum(j), i); + } + + cnt = 0; + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + int nelv = el.GetNV(); + for (j = 1; j <= nelv; j++) + cnt.Elem(el.PNum(j))++; + } + + vert2surfelement = new TABLE<int> (cnt); + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + int nelv = el.GetNV(); + for (j = 1; j <= nelv; j++) + vert2surfelement->AddSave (el.PNum(j), i); + } + + + cnt = 0; + for (i = 1; i <= nseg; i++) + { + const Segment & seg = mesh.LineSegment(i); + cnt.Elem (seg.p1)++; + cnt.Elem (seg.p2)++; + } + + vert2segment = new TABLE<int> (cnt); + for (i = 1; i <= nseg; i++) + { + const Segment & seg = mesh.LineSegment(i); + vert2segment->AddSave (seg.p1, i); + vert2segment->AddSave (seg.p2, i); + } + + + + (*testout) << "before buildedges" << endl; + + + if (buildedges) + { + PrintMessage (5, "Update edges "); + + edges.SetSize(ne); + surfedges.SetSize(nse); + segedges.SetSize(nseg); + + for (i = 1; i <= ne; i++) + for (j = 0; j < 12; j++) + edges.Elem(i)[j] = 0; + for (i = 1; i <= nse; i++) + for (j = 0; j < 4; j++) + surfedges.Elem(i)[j] = 0; + + // keep existing edges + cnt = 0; + for (i = 1; i <= edge2vert.Size(); i++) + cnt.Elem(edge2vert.Get(i)[0])++; + TABLE<int> vert2edge (cnt); + for (i = 1; i <= edge2vert.Size(); i++) + vert2edge.AddSave (edge2vert.Get(i)[0], i); + + // ensure all coarse grid and intermediate level edges + cnt = 0; + for (i = 1; i <= mesh.mlbetweennodes.Size(); i++) + { + int pa[2]; + pa[0] = mesh.mlbetweennodes.Get(i).I1(); + pa[1] = mesh.mlbetweennodes.Get(i).I2(); + if (pa[0] > pa[1]) Swap (pa[0], pa[1]); + if (pa[0] > 0) + cnt.Elem(pa[0])++; + } + TABLE<int> vert2vertcoarse (cnt); + for (i = 1; i <= mesh.mlbetweennodes.Size(); i++) + { + int pa[2]; + pa[0] = mesh.mlbetweennodes.Get(i).I1(); + pa[1] = mesh.mlbetweennodes.Get(i).I2(); + if (pa[0] > pa[1]) Swap (pa[0], pa[1]); + if (pa[0] > 0) + vert2vertcoarse.AddSave (pa[0], pa[1]); + } + + + ARRAY<int> edgenr(nv), edgeflag(nv); + for (i = 1; i <= nv; i++) + edgeflag.Elem(i) = 0; + ned = edge2vert.Size(); + ARRAY<INDEX_3> missing; + + for (i = 1; i <= nv; i++) + { + for (j = 1; j <= vert2edge.EntrySize(i); j++) + { + int ednr = vert2edge.Get(i,j); + int i2 = edge2vert.Get(ednr)[1]; + edgeflag.Elem(i2) = i; + edgenr.Elem(i2) = ednr; + } + for (j = 1; j <= vert2vertcoarse.EntrySize(i); j++) + { + int v2 = vert2vertcoarse.Get(i,j); + if (edgeflag.Get(v2) < i) + { + ned++; + edgenr.Elem(v2) = ned; + edgeflag.Elem(v2) = i; + missing.Append (INDEX_3(i,v2,ned)); + } + } + + for (j = 1; j <= vert2element->EntrySize(i); j++) + { + int elnr = vert2element->Get(i,j); + const Element & el = mesh.VolumeElement (elnr); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges (el.GetType()); + + for (k = 0; k < neledges; k++) + { + INDEX_2 edge(el.PNum(eledges[k][0]), + el.PNum(eledges[k][1])); + + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) Swap (edge.I1(), edge.I2()); + + if (edge.I1() != i) + continue; + + if (edgeflag.Get (edge.I2()) < i) + { + ned++; + edgenr.Elem(edge.I2()) = ned; + edgeflag.Elem(edge.I2()) = i; + } + + int edgenum = edgenr.Elem(edge.I2()); + if (edgedir) edgenum *= -1; + edges.Elem(elnr)[k] = edgenum; + } + } + + for (j = 1; j <= vert2surfelement->EntrySize(i); j++) + { + int elnr = vert2surfelement->Get(i,j); + const Element2d & el = mesh.SurfaceElement (elnr); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges (el.GetType()); + + for (k = 0; k < neledges; k++) + { + INDEX_2 edge(el.PNum(eledges[k][0]), + el.PNum(eledges[k][1])); + + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) Swap (edge.I1(), edge.I2()); + + if (edge.I1() != i) + continue; + + if (edgeflag.Get (edge.I2()) < i) + { + ned++; + edgenr.Elem(edge.I2()) = ned; + edgeflag.Elem(edge.I2()) = i; + } + + int edgenum = edgenr.Elem(edge.I2()); + if (edgedir) edgenum *= -1; + surfedges.Elem(elnr)[k] = edgenum; + } + } + + for (j = 1; j <= vert2segment->EntrySize(i); j++) + { + int elnr = vert2segment->Get(i,j); + const Segment & el = mesh.LineSegment (elnr); + + INDEX_2 edge(el.p1, el.p2); + + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) Swap (edge.I1(), edge.I2()); + + if (edge.I1() != i) + continue; + + if (edgeflag.Get (edge.I2()) < i) + { + ned++; + edgenr.Elem(edge.I2()) = ned; + edgeflag.Elem(edge.I2()) = i; + } + int edgenum = edgenr.Elem(edge.I2()); + + if (edgedir) edgenum *= -1; + segedges.Elem(elnr) = edgenum; + } + } + + + edge2vert.SetSize (ned); + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement (i); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges (el.GetType()); + + for (k = 0; k < neledges; k++) + { + INDEX_2 edge(el.PNum(eledges[k][0]), + el.PNum(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(); + } + } + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement (i); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges (el.GetType()); + + for (k = 0; k < neledges; k++) + { + INDEX_2 edge(el.PNum(eledges[k][0]), + el.PNum(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 (i = 1; i <= nseg; i++) + { + const Segment & el = mesh.LineSegment (i); + + INDEX_2 edge(el.p1, el.p2); + 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 (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 (i = 1; i <= edge2vert.Size(); i++) + (*testout) << "edge " << i << ", v1,2 = " << edge2vert.Elem(i)[0] << ", " << edge2vert.Elem(i)[1] << endl; + (*testout) << "surfedges:" << endl; + for (i = 1; i <= surfedges.Size(); i++) + (*testout) << "el " << i << ", edges = " + << surfedges.Elem(i)[0] << ", " + << surfedges.Elem(i)[1] << ", " + << surfedges.Elem(i)[2] << endl; + */ + } + +#ifdef OLD + if (buildedges == 2) + { // old style with hash-table + edges.SetSize(ne); + surfedges.SetSize(nse); + INDEX_2_HASHTABLE<int> vert2edge(ne+nse+1); + + // keep coarse grid edges + for (i = 1; i <= ned; i++) + { + INDEX_2 edge (edge2vert.Get(i)[0], + edge2vert.Get(i)[1]); + edge.Sort (); + vert2edge.Set (edge, i); + } + + + + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges (el.GetType()); + + for (j = 0; j < 12; j++) + edges.Elem(i)[j] = 0; + for (j = 0; j < neledges; j++) + { + int edgenum; + int edgedir; + + INDEX_2 edge(el.PNum(eledges[j][0]), + el.PNum(eledges[j][1])); + + edgedir = (edge.I1() > edge.I2()); + if (edgedir) Swap (edge.I1(), edge.I2()); + + if (vert2edge.Used (edge)) + edgenum = vert2edge.Get(edge); + else + { + ned++; + vert2edge.Set (edge, ned); + edgenum = ned; + /* + edge2vert.SetSize(edge2vert.Size()+1); + edge2vert.Last()[0] = edge.I1(); + edge2vert.Last()[1] = edge.I2(); + */ + edge2vert.Append (edge); + } + + if (edgedir) edgenum *= -1; + edges.Elem(i)[j] = edgenum; + } + } + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges (el.GetType()); + + for (j = 0; j < 4; j++) + surfedges.Elem(i)[j] = 0; + for (j = 0; j < neledges; j++) + { + int edgenum; + int edgedir; + + INDEX_2 edge(el.PNum(eledges[j][0]), + el.PNum(eledges[j][1])); + + edgedir = (edge.I1() > edge.I2()); + if (edgedir) Swap (edge.I1(), edge.I2()); + + if (vert2edge.Used (edge)) + edgenum = vert2edge.Get(edge); + else + { + ned++; + vert2edge.Set (edge, ned); + edgenum = ned; + + /* + edge2vert.SetSize(edge2vert.Size()+1); + edge2vert.Last()[0] = edge.I1(); + edge2vert.Last()[1] = edge.I2(); + */ + edge2vert.Append (edge); + if (mesh.GetDimension() == 3 && mesh.GetNE()) + cerr << "surface edge: should be in use: " + << edge.I1() << "-" << edge.I2() << endl; + } + + if (edgedir) edgenum *= -1; + surfedges.Elem(i)[j] = edgenum; + } + } + + + // find edges only in intermediate level + + for (i = 1; i <= np; i++) + { + int parents[2]; + + if (i <= mesh.mlbetweennodes.Size()) + { + parents[0] = mesh.mlbetweennodes.Get(i).I1(); + parents[1] = mesh.mlbetweennodes.Get(i).I2(); + } + else + parents[0] = parents[1] = 0; + + if (parents[0] && parents[1]) + { + INDEX_2 edge(parents[0], parents[1]); + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) Swap (edge.I1(), edge.I2()); + + if (!vert2edge.Used (edge)) + { + ned++; + vert2edge.Set (edge, ned); + /* + edge2vert.SetSize(edge2vert.Size()+1); + edge2vert.Last()[0] = edge.I1(); + edge2vert.Last()[1] = edge.I2(); + */ + edge2vert.Append (edge); + } + } + } + + /* + cout << "edge2vert: "; + edge2vert.PrintMemInfo(cout); + cout << "edges: "; + edges.PrintMemInfo(cout); + cout << "hashtable: "; + vert2edge.PrintMemInfo(cout); + */ + + if (mesh.GetDimension() == 2) + { + surffaces.SetSize(mesh.GetNSeg()); + for (i = 1; i <= mesh.GetNSeg(); i++) + { + const Segment & seg = mesh.LineSegment (i); + + INDEX_2 edge(seg.p1, seg.p2); + int edgenum; + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) Swap (edge.I1(), edge.I2()); + + if (vert2edge.Used (edge)) + edgenum = vert2edge.Get(edge); + else + { + ned++; + vert2edge.Set (edge, ned); + edgenum = ned; + + /* + edge2vert.SetSize(edge2vert.Size()+1); + edge2vert.Last()[0] = edge.I1(); + edge2vert.Last()[1] = edge.I2(); + */ + edge2vert.Append (edge); + } + + + if (edgedir) edgenum *= -1; + surffaces.Elem(i) = edgenum; + } + } + } + +#endif + + + // generate faces + if (buildfaces) // && mesh.GetDimension() == 3) + { + PrintMessage (5, "Update faces "); + + faces.SetSize(ne); + surffaces.SetSize(nse); + + // face2vert.SetSize(0); // keep old faces + nfa = face2vert.Size(); + // INDEX_3_HASHTABLE<int> vert2face(ne+nse+1); + INDEX_3_CLOSED_HASHTABLE<int> vert2face(8*ne+2*nse+nfa+2); + + for (i = 1; i <= face2vert.Size(); i++) + { + INDEX_3 f; + f.I1() = face2vert.Get(i)[0]; + f.I2() = face2vert.Get(i)[1]; + f.I3() = face2vert.Get(i)[2]; + vert2face.Set (f, i); + } + + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement (i); + + int nelfaces = GetNFaces (el.GetType()); + const ELEMENT_FACE * elfaces = GetFaces (el.GetType()); + + for (j = 0; j < 6; j++) + faces.Elem(i)[j] = 0; + for (j = 0; j < nelfaces; j++) + if (elfaces[j][3] == 0) + + { // triangle + + int facenum; + int 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 (vert2face.Used (face)) + facenum = vert2face.Get(face); + else + { + nfa++; + vert2face.Set (face, nfa); + facenum = nfa; + + INDEX_4 hface; + face2vert.Append (hface); + // face2vert.SetSize(face2vert.Size()+1); + face2vert.Last()[0] = face.I1(); + face2vert.Last()[1] = face.I2(); + face2vert.Last()[2] = face.I3(); + face2vert.Last()[3] = 0; + + } + + faces.Elem(i)[j] = 8*(facenum-1)+facedir+1; + } + + else + + { + // quad + int facenum; + int 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()); + } + // face4.Sort(); + + INDEX_3 face(face4.I1(), face4.I2(), face4.I3()); + + if (vert2face.Used (face)) + { + facenum = vert2face.Get(face); + } + else + { + nfa++; + vert2face.Set (face, nfa); + facenum = nfa; + + // face2vert.SetSize(face2vert.Size()+1); + + INDEX_4 hface; + face2vert.Append (hface); + face2vert.Last()[0] = face4.I1(); + face2vert.Last()[1] = face4.I2(); + face2vert.Last()[2] = face4.I3(); + face2vert.Last()[3] = face4.I4(); + + } + + faces.Elem(i)[j] = 8*(facenum-1)+facedir+1; + } + } + + face2surfel.SetSize(nfa+nse); + for (i = 1; i <= face2surfel.Size(); i++) + face2surfel.Elem(i) = 0; + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement (i); + + const ELEMENT_FACE * elfaces = GetFaces (el.GetType()); + + if (elfaces[0][3] == 0) + + { // triangle + + int facenum; + int facedir; + + INDEX_3 face(el.PNum(elfaces[0][0]), + el.PNum(elfaces[0][1]), + el.PNum(elfaces[0][2])); + + facedir = 0; + if (face.I1() > face.I2()) + { + Swap (face.I1(), face.I2()); + facedir += 1; + } + if (face.I2() > face.I3()) + { + Swap (face.I2(), face.I3()); + facedir += 2; + } + if (face.I1() > face.I2()) + { + Swap (face.I1(), face.I2()); + facedir += 4; + } + + if (vert2face.Used (face)) + facenum = vert2face.Get(face); + else + { + nfa++; + vert2face.Set (face, nfa); + facenum = nfa; + + // face2vert.SetSize(face2vert.Size()+1); + INDEX_4 hface; + face2vert.Append (hface); + face2vert.Last()[0] = face.I1(); + face2vert.Last()[1] = face.I2(); + face2vert.Last()[2] = face.I3(); + face2vert.Last()[3] = 0; + } + + surffaces.Elem(i) = 8*(facenum-1)+facedir+1; + face2surfel.Elem(facenum) = i; + } + + 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 (vert2face.Used (face)) + facenum = vert2face.Get(face); + else + { + nfa++; + vert2face.Set (face, nfa); + facenum = nfa; + + // face2vert.SetSize(face2vert.Size()+1); + INDEX_4 hface; + face2vert.Append (hface); + face2vert.Last()[0] = face4.I1(); + face2vert.Last()[1] = face4.I2(); + face2vert.Last()[2] = face4.I3(); + face2vert.Last()[3] = face4.I3(); + } + + surffaces.Elem(i) = 8*(facenum-1)+facedir+1; + face2surfel.Elem(facenum) = i; + } + } + + surf2volelement.SetSize (nse); + for (i = 1; i <= nse; i++) + { + surf2volelement.Elem(i)[0] = 0; + surf2volelement.Elem(i)[1] = 0; + } + for (i = 1; i <= ne; i++) + for (j = 0; j < 6; j++) + { + int fnum = (faces.Get(i)[j]-1) / 8 + 1; + if (fnum > 0 && face2surfel.Elem(fnum)) + { + int sel = face2surfel.Elem(fnum); + surf2volelement.Elem(sel)[1] = + surf2volelement.Elem(sel)[0]; + surf2volelement.Elem(sel)[0] = i; + } + } + + + face2vert.SetAllocSize (face2vert.Size()); + + /* + cout << "face2vert: "; + face2vert.PrintMemInfo(cout); + cout << "faces: "; + faces.PrintMemInfo(cout); + cout << "hashtable: "; + vert2face.PrintMemInfo(cout); + */ + } + + /* + for (i = 1; i <= ne; i++) + { + (*testout) << "Element " << i << endl; + (*testout) << "edges: " << endl; + for (j = 0; j < 9; j++) + (*testout) << edges.Elem(i)[j] << " "; + (*testout) << "faces: " << endl; + for (j = 0; j < 6; j++) + (*testout) << faces.Elem(i)[j] << " "; + } + */ + timestamp = NextTimeStamp(); +} + + + + +int MeshTopology :: GetNVertices (ELEMENT_TYPE et) +{ + switch (et) + { + case SEGMENT: + case SEGMENT3: + return 2; + + case TRIG: + case TRIG6: + return 3; + + case QUAD: + case QUAD6: + 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 :: GetNEdges (ELEMENT_TYPE et) +{ + switch (et) + { + case SEGMENT: + case SEGMENT3: + return 1; + + case TRIG: + case TRIG6: + return 3; + + case QUAD: + case QUAD6: + 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: + 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 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: + 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; +} + + + + +const ELEMENT_EDGE * MeshTopology :: GetEdges (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: + 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 :: GetFaces (ELEMENT_TYPE et) +{ + static int trig_faces[1][4] = + { { 1, 2, 3, 0 } }; + static int quad_faces[1][4] = + { { 1, 2, 3, 4 } }; + + 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 hex_faces[6][4] = + { + { 1, 2, 3, 4 }, + { 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: + 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; +} + + + + + + + + + + + + +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) const +{ + int i; + int nfa = GetNFaces (mesh.VolumeElement(elnr).GetType()); + elfaces.SetSize (nfa); + for (i = 1; i <= nfa; i++) + elfaces.Elem(i) = (faces.Get(elnr)[i-1]-1) / 8 + 1; +} + +void MeshTopology :: GetElementEdgeOrientations (int elnr, ARRAY<int> & eorient) const +{ + int i; + int ned = GetNEdges (mesh.VolumeElement(elnr).GetType()); + eorient.SetSize (ned); + for (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 i; + int nfa = GetNFaces (mesh.VolumeElement(elnr).GetType()); + forient.SetSize (nfa); + for (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 i; + // int ned = GetNEdges (mesh.VolumeElement(elnr).GetType()); + + if (mesh.GetDimension()==3 || 1) + { + if (orient) + { + for (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 (i = 0; i < 12; i++) + { + if (!edges.Get(elnr)[i]) return i; + eledges[i] = abs (edges.Get(elnr)[i]); + } + } + return 12; + } + else + { + 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 i; + // int nfa = GetNFaces (mesh.VolumeElement(elnr).GetType()); + if (orient) + { + for (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 (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 i; + int ned = GetNEdges (mesh.SurfaceElement(elnr).GetType()); + eorient.SetSize (ned); + for (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> & edges) const +{ + ArrayMem<int,4> pi(4); + // ArrayMem<int,50> els; + ArrayMem<int,12> eledges; + + edges.SetSize (0); + GetFaceVertices (fnr, pi); + // GetVertexElements (pi[0], els); + FlatArray<int> els = GetVertexElements (pi[0]); + + // find one element having all vertices of the face + int i, j, k; + for (i = 0; i < els.Size(); i++) + { + const Element & el = mesh.VolumeElement(els[i]); + + int cntv = 0; + for (j = 0; j < el.GetNV(); j++) + for (k = 0; k < pi.Size(); k++) + if (el[j] == pi[k]) + cntv++; + + if (cntv == pi.Size()) + { + GetElementEdges (els[i], eledges); + + for (j = 0; j < eledges.Size(); j++) + { + int vi1, vi2; + GetEdgeVertices (eledges[j], vi1, vi2); + bool has1 = 0; + bool has2 = 0; + for (k = 0; k < pi.Size(); k++) + { + if (vi1 == pi[k]) has1 = 1; + if (vi2 == pi[k]) has2 = 1; + } + if (has1 && has2) + edges.Append (eledges[j]); + } + + 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-1]; + return FlatArray<int> (0,0); +} + + +} diff --git a/Netgen/libsrc/meshing/topology.hpp b/Netgen/libsrc/meshing/topology.hpp new file mode 100644 index 0000000000..751034be49 --- /dev/null +++ b/Netgen/libsrc/meshing/topology.hpp @@ -0,0 +1,109 @@ +#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; + int buildedges; + int 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> *vert2element; + TABLE<int> *vert2surfelement; + TABLE<int> *vert2segment; + int timestamp; +public: + MeshTopology (const Mesh & amesh); + + void SetBuildEdges (int be) + { buildedges = be; } + void SetBuildFaces (int bf) + { buildfaces = bf; } + + int HasEdges () const + { return buildedges; } + int HasFaces () const + { return buildedges; } + + void Update(); + + + int GetNEdges () const + { return edge2vert.Size(); } + int GetNFaces () const + { return face2vert.Size(); } + + static int GetNVertices (ELEMENT_TYPE et); + static int GetNEdges (ELEMENT_TYPE et); + static int GetNFaces (ELEMENT_TYPE et); + + static const Point3d * GetVertices (ELEMENT_TYPE et); + static const ELEMENT_EDGE * GetEdges (ELEMENT_TYPE et); + static const ELEMENT_FACE * GetFaces (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) 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 fnr, int & v1, int & v2) const; + void GetFaceEdges (int fnr, ARRAY<int> & edges) 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; + + 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; +}; + +#endif diff --git a/Netgen/libsrc/meshing/triarls.cpp b/Netgen/libsrc/meshing/triarls.cpp new file mode 100644 index 0000000000..923763306d --- /dev/null +++ b/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 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/Netgen/libsrc/meshing/zrefine.cpp b/Netgen/libsrc/meshing/zrefine.cpp new file mode 100644 index 0000000000..70dc91e1ca --- /dev/null +++ b/Netgen/libsrc/meshing/zrefine.cpp @@ -0,0 +1,735 @@ +#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) + { + int i, j; + + // edges selected in csg input file + for (i = 1; i <= geom.singedges.Size(); i++) + { + const SingularEdge & se = *geom.singedges.Get(i); + for (j = 1; j <= se.segms.Size(); j++) + { + INDEX_2 i2 = se.segms.Get(j); + singedges.Set (i2, 1); + } + } + + // edges interactively selected + for (i = 1; i <= mesh.GetNSeg(); i++) + { + const Segment & seg = mesh.LineSegment(i); + if (seg.singedge) + { + INDEX_2 i2(seg.p1, seg.p2); + i2.Sort(); + singedges.Set (i2, 1); + } + } + } + + + /** + Convert elements (vol-tets, surf-trigs) into prisms/quads + */ + void MakePrismsSingEdge (Mesh & mesh, INDEX_2_HASHTABLE<int> & singedges) + { + int i, j, k; + + // volume elements + for (i = 1; i <= mesh.GetNE(); i++) + { + Element & el = mesh.VolumeElement(i); + if (el.GetType() != TET) continue; + + 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 (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 (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 (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).p1 : + mesh.LineSegment(i).p2; + 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, k; + 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; + + 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(); + double slicefac = slices.Get(slicenr); + double slicefaclast = + (slicenr == slices.Size()) ? 1 : slices.Get(slicenr+1); + + Point3d np = p1 + (slicefac / slicefaclast) * (p2-p1); + 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.p1, el.p2); + 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.p1), + // mesh.Point (el.p2), + // el.surfnr1, el.surfnr2, + // el.epgeominfo[0], el.epgeominfo[1], + // pb, ngi); + // */ + // pb = Center (mesh.Point (el.p1), mesh.Point (el.p2)); + + // 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.p2 = pnew; + ns1.epgeominfo[1] = ngi; + ns2.p1 = 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 CSGeometry * geom, + ZRefinementOptions & opt) + { + 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/Netgen/libsrc/occ/Makefile b/Netgen/libsrc/occ/Makefile new file mode 100644 index 0000000000..6fe1d8bc0d --- /dev/null +++ b/Netgen/libsrc/occ/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for open cascade library +# +src = occgeom.cpp occmeshsurf.cpp occgenmesh.cpp + +lib = occ +libpath = libsrc/occ +# +# +include ../makefile.inc + diff --git a/Netgen/libsrc/occ/occgenmesh.cpp b/Netgen/libsrc/occ/occgenmesh.cpp new file mode 100644 index 0000000000..f7055eb027 --- /dev/null +++ b/Netgen/libsrc/occ/occgenmesh.cpp @@ -0,0 +1,666 @@ +#ifdef OCCGEOMETRY + +#include <mystdlib.h> +#include <occgeom.hpp> +#include <meshing.hpp> + +namespace netgen +{ + +#include "occmeshsurf.hpp" + +#define TCL_OK 0 +#define TCL_ERROR 1 + + +void DivideEdge (TopoDS_Edge & edge, ARRAY <MeshPoint> & ps, ARRAY<double> & params, Mesh & mesh) +{ + double s0, s1; + int j; + double maxh = mparam.maxh; + int nsubedges = 1; + gp_Pnt pnt; + double svalue[1000]; + + GProp_GProps system; + BRepGProp::LinearProperties(edge, system); + double L = system.Mass(); + + Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1); + + double s = s0; + j = 0; + while (s < s1) + { + pnt = c->Value(s); + svalue[j] = s; + s += mesh.GetH(Point3d(pnt.X(), pnt.Y(), pnt.Z()))*(s1-s0)/L; + j++; + if (s < s1) nsubedges++; + } + svalue[j] = s; + double stretchfac = (s1-s0)/(s-s0); + + if (nsubedges < mparam.segmentsperedge) + { + nsubedges = 1; + s = s0; + j = 0; + while (s < s1) + { + pnt = c->Value(s); + svalue[j] = s; + s += min ((s1-s0)/mparam.segmentsperedge, mesh.GetH(Point3d(pnt.X(), pnt.Y(), pnt.Z()))*(s1-s0)/L); + j++; + if (s < s1) nsubedges++; + } + svalue[j] = s; + stretchfac = (s1-s0)/(s-s0); + } + + ps.SetSize (nsubedges-1); + params.SetSize (nsubedges+1); + + for (j = 1; j < nsubedges; j++) + { + params[j] = s0+stretchfac*(svalue[j]-s0); + pnt = c->Value(params[j]); + ps[j-1] = MeshPoint (Point3d(pnt.X(), pnt.Y(), pnt.Z())); + } + + params[0] = s0; + params[nsubedges] = s1; +} + + + +static void FindEdges (OCCGeometry & geom, Mesh & mesh) +{ + int i, j; + + TopExp_Explorer exp0, exp01, exp1, exp2, exp3; + + int nvertices = geom.vmap.Extent(); + int nedges = geom.emap.Extent(); + for (i = 1; i <= nvertices; i++) + { + gp_Pnt pnt = BRep_Tool::Pnt (TopoDS::Vertex(geom.vmap(i))); + MeshPoint mp( Point3d(pnt.X(), pnt.Y(), pnt.Z()) ); + mesh.AddPoint (mp); + } + + int facenr = 0; + int edgenr = 0; + + for (exp0.Init(geom.shape, TopAbs_SOLID); exp0.More(); exp0.Next()) + for (exp01.Init(exp0.Current(), TopAbs_SHELL); exp01.More(); exp01.Next()) + { + TopoDS_Shape shell = exp01.Current(); + + for (exp1.Init(shell, TopAbs_FACE); exp1.More(); exp1.Next()) + { + TopoDS_Face face = TopoDS::Face(exp1.Current()); + + facenr = geom.fmap.FindIndex (face); + + mesh.AddFaceDescriptor (FaceDescriptor(facenr, 1, 0, 0)); + Handle(Geom_Surface) occface = BRep_Tool::Surface(face); + + for (exp2.Init (face, TopAbs_WIRE); exp2.More(); exp2.Next()) + { + TopoDS_Shape wire = exp2.Current(); + + for (exp3.Init (wire, TopAbs_EDGE); exp3.More(); exp3.Next()) + { + TopoDS_Edge edge = TopoDS::Edge (exp3.Current()); + if (BRep_Tool::Degenerated(edge)) 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); + + pnums[0] = geom.vmap.FindIndex (TopExp::FirstVertex (edge)); + pnums[pnums.Size()-1] = geom.vmap.FindIndex (TopExp::LastVertex (edge)); + + for (i = 1; i <= mp.Size(); i++) + { + int exists = 0; + + for (j = 1; !exists && (j <= mesh.GetNP()-nvertices); j++) + if ((mesh.Point(nvertices+j)-Point<3>(mp[i-1])).Length() < 1e-6) exists = 1; + if (exists) + { + pnums[i] = nvertices+j-1; + } + else + { + mesh.AddPoint (mp[i-1]); + pnums[i] = mesh.GetNP(); + } + } + + for (i = 1; i <= mp.Size()+1; i++) + { + edgenr++; + Segment seg; + + seg.p1 = pnums[i-1]; + seg.p2 = 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]); + seg.epgeominfo[0].u = p2d.X(); + seg.epgeominfo[0].v = p2d.Y(); + p2d = cof->Value(params[i]); + seg.epgeominfo[1].u = p2d.X(); + seg.epgeominfo[1].v = p2d.Y(); + + if (edge.Orientation() == TopAbs_REVERSED) + { + swap (seg.p1, seg.p2); + 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); + + // (*testout) << "seg" << seg.edgenr << ": " << seg.p1 << " - " << seg.p2 << endl; + } + } + } + } + } + mesh.CalcSurfacesOfNode(); +} + + + + +static void OCCMeshSurface (OCCGeometry & geom, Mesh & mesh, int perfstepsend) +{ + int i, j, k; + int changed; + + char * savetask = multithread.task; + multithread.task = "Surface meshing"; + + int noldp = mesh.GetNP(); + + double starttime = GetTime(); + + ARRAY<int> glob2loc(noldp); + + for (k = 1; k <= mesh.GetNFD(); k++) + { + + (*testout) << "mesh face " << k << endl; + multithread.percent = 100 * k / (mesh.GetNFD()+1e-10); + + FaceDescriptor & fd = mesh.GetFaceDescriptor(k); + + PrintMessage (2, "Surface ", k, " / ", mesh.GetNFD()); + + int oldnf = mesh.GetNSE(); + + + Box<3> bb (Point<3> (-geom.MaxSize(), -geom.MaxSize(), -geom.MaxSize()), + Point<3> (geom.MaxSize(), geom.MaxSize(), geom.MaxSize())); + + Meshing2OCCSurfaces meshing(TopoDS::Face(geom.fmap(k)), bb); + // Meshing2OCCSurfaces meshing(f2, bb); + meshing.SetStartTime (starttime); + + /* + for (i = 1; i <= noldp; i++) + { + // (*testout) << "Add point " << mesh.Point(i) << endl; + meshing.AddPoint (mesh.Point(i), i); + } + */ + + 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.p1 : seg.p2; + 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.p1), glob2loc.Get(seg.p2), gi0, gi1); + + (*testout) << "Add BE " << seg.p1 << "-" << seg.p2 << " (" << ")" << endl; + } + } + + double maxh = mparam.maxh; + + MESHING2_RESULT res = + meshing.GenerateMesh (mesh, maxh, k); + + if (res != MESHING2_OK) + { + PrintError ("Problem in Surface mesh generation"); + throw NgException ("Problem in Surface mesh generation"); + } + + for (i = oldnf+1; i <= mesh.GetNSE(); i++) + mesh.SurfaceElement(i).SetIndex (k); + + } + + if (multithread.terminate || perfstepsend < MESHCONST_OPTSURFACE) + return; + + multithread.task = "Optimizing surface"; + + for (k = 1; k <= mesh.GetNFD(); k++) + { + (*testout) << "optimize face " << k << endl; + multithread.percent = 100 * k / (mesh.GetNFD()+1e-10); + + FaceDescriptor & fd = mesh.GetFaceDescriptor(k); + + PrintMessage (1, "Optimize Surface ", k); + for (i = 1; i <= mparam.optsteps2d; i++) + { + if (multithread.terminate) return; + + { + MeshOptimize2dOCCSurfaces meshopt(geom); + meshopt.SetFaceIndex (k); + meshopt.SetImproveEdges (0); + meshopt.SetMetricWeight (0.2); + meshopt.SetWriteStatus (0); + + 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.SetWriteStatus (0); + + meshopt.ImproveMesh (mesh); + } + + { + MeshOptimize2dOCCSurfaces meshopt(geom); + meshopt.SetFaceIndex (k); + meshopt.SetImproveEdges (0); + meshopt.SetMetricWeight (0.2); + meshopt.SetWriteStatus (0); + + meshopt.CombineImprove (mesh); + } + + if (multithread.terminate) return; + { + MeshOptimize2dOCCSurfaces meshopt(geom); + meshopt.SetFaceIndex (k); + meshopt.SetImproveEdges (0); + meshopt.SetMetricWeight (0.2); + meshopt.SetWriteStatus (0); + + meshopt.ImproveMesh (mesh); + } + } + + } + + + mesh.CalcSurfacesOfNode(); + mesh.Compress(); + + multithread.task = savetask; +} + +double ComputeH (double kappa) +{ + double hret; + kappa *= mparam.curvaturesafety; + + if (mparam.maxh * kappa < 1) + hret = mparam.maxh; + else + hret = 1 / kappa; + + if (mparam.maxh < hret) + hret = mparam.maxh; + + return (hret); +} + + +int OCCGenerateMesh (OCCGeometry & geom, + Mesh *& mesh, + int perfstepsstart, int perfstepsend, + char * optstr) +{ + int i, j; + + if (perfstepsstart <= MESHCONST_ANALYSE) + { + delete mesh; + mesh = new Mesh(); + + mesh->SetGlobalH (mparam.maxh); + + ARRAY<double> maxhdom(1); + maxhdom[0] = mparam.maxh; + double maxsize = geom.MaxSize(); + + mesh->SetMaxHDomain (maxhdom); + mesh->SetLocalH (Point<3>(-maxsize, -maxsize, -maxsize), + Point<3>(maxsize, maxsize, maxsize), + 0.5); + + if (mparam.uselocalh) + { + + char * savetask = multithread.task; + multithread.task = "Setting local mesh size"; + + double maxsize = geom.MaxSize(); + mesh->SetLocalH (Point<3>(-maxsize, -maxsize, -maxsize), + Point<3>(maxsize, maxsize, maxsize), + mparam.grading); + + cout << "maxsize = " << maxsize << endl; + + int nfaces = geom.fmap.Extent(); + + int i; + for (i = 1; i <= nfaces; i++) + { + (*testout) << "face " << i << endl; + 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); + BRepAdaptor_Surface sf(face, Standard_False); + BRepLProp_SLProps prop(sf, 2, 1e-5); + + int ntriangles = triangulation -> NbTriangles(); + for (j = 1; j <= ntriangles; j++) + { + int k; + gp_Pnt p[3]; + gp_Pnt2d par[3]; + + for (k = 1; k <=3; k++) + { + int n = triangulation->Triangles()(j)(k); + p[k-1] = triangulation->Nodes()(n); + par[k-1] = triangulation->UVNodes()(n); + } + + double lp2p0 = p[2].Distance(p[0]); + double lp2p1 = p[2].Distance(p[1]); + + prop.SetParameters (p[2].X(), p[2].Y()); + double h; + + if (!prop.IsCurvatureDefined()) continue; + + h = ComputeH (max(fabs(prop.MinCurvature()), + fabs(prop.MaxCurvature()))+1e-10); + + double h0 = h/lp2p0; + double h1 = h/lp2p1; + + h0 = min (h0, 1.0); + h1 = min (h1, 1.0); + + double l0, l1, l2; + for (l0 = 0; l0 <= 1; l0+=h0) + for (l1 = 0; l1 <= 1-l0; l1+=h1) + { + l2 = 1-l0-l1; + double u = l0*par[0].X() + l1*par[1].X() + l2*par[2].X(); + double v = l0*par[0].Y() + l1*par[1].Y() + l2*par[2].Y(); + + prop.SetParameters (u, v); + + if (!prop.IsCurvatureDefined()) continue; + + gp_Pnt pnt = prop.Value(); + + mesh->RestrictLocalH (Point3d(pnt.X(), pnt.Y(), pnt.Z()), + ComputeH (max(fabs(prop.MinCurvature()), + fabs(prop.MaxCurvature()))+1e-10)); + } + + } + + /* + // schmale lange drei+viereckerl + TopExp_Explorer exp; + for (exp.Init (face, TopAbs_WIRE); exp.More(); exp.Next()) + { + bool done = 0; + BRepTools_WireExplorer wexp; + double L[4]; + GProp_GProps system; + int i = 0; + double minL = 1e10; + + for (wexp.Init (TopoDS::Wire(exp.Current())); wexp.More() && i < 4; wexp.Next()) + { + BRepGProp::LinearProperties(wexp.Current(), system); + L[i++] = system.Mass(); + minL = min (minL, L[i-1]); + } + + if (i == 4 && wexp.More()) continue; // more that 4 edges + + + double h = minL; + + for (j = 1; j <= ntriangles; j++) + { + int k; + gp_Pnt p[3]; + gp_Pnt2d par[3]; + + for (k = 1; k <=3; k++) + { + int n = triangulation->Triangles()(j)(k); + p[k-1] = triangulation->Nodes()(n); + par[k-1] = triangulation->UVNodes()(n); + } + + double lp2p0 = p[2].Distance(p[0]); + double lp2p1 = p[2].Distance(p[1]); + + prop.SetParameters (p[2].X(), p[2].Y()); + + double h0 = h/lp2p0; + double h1 = h/lp2p1; + + h0 = min (h0, 1.0); + h1 = min (h1, 1.0); + + double l0, l1, l2; + for (l0 = 0; l0 <= 1; l0+=h0) + for (l1 = 0; l1 <= 1-l0; l1+=h1) + { + l2 = 1-l0-l1; + double u = l0*par[0].X() + l1*par[1].X() + l2*par[2].X(); + double v = l0*par[0].Y() + l1*par[1].Y() + l2*par[2].Y(); + + prop.SetParameters (u, v); + gp_Pnt pnt = prop.Value(); + + mesh->RestrictLocalH (Point3d(pnt.X(), pnt.Y(), pnt.Z()), h); + } + + } + } + */ + + + } + + multithread.task = savetask; + } + } + + + if (multithread.terminate || perfstepsend <= MESHCONST_ANALYSE) + return TCL_OK; + + if (perfstepsstart <= MESHCONST_MESHEDGES) + { + FindEdges (geom, *mesh); + +#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); + + 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, NULL); + 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 (i = 1; i <= mesh->GetNP(); i++) + (*testout) << mesh->Point(i) << endl; + + (*testout) << endl << "NSegments: " << mesh->GetNSeg() << endl; + for (i = 1; i <= mesh->GetNSeg(); i++) + (*testout) << mesh->LineSegment(i) << endl; + + + + return TCL_OK; +} +} + +#endif diff --git a/Netgen/libsrc/occ/occgeom.cpp b/Netgen/libsrc/occ/occgeom.cpp new file mode 100644 index 0000000000..bc50d82975 --- /dev/null +++ b/Netgen/libsrc/occ/occgeom.cpp @@ -0,0 +1,106 @@ +#ifdef OCCGEOMETRY + +#include <mystdlib.h> +#include <occgeom.hpp> + + +namespace netgen +{ + +void PrintContents (OCCGeometry * geom) +{ + TopExp_Explorer exp0; + int cnt; + + (*testout) << "OCC CONTENTS" << endl + << "============" << endl; + + for (cnt = 0, exp0.Init(geom->shape, TopAbs_COMPOUND); exp0.More(); exp0.Next()) cnt++; + (*testout) << "COMPOUND : " << cnt << endl; + + for (cnt = 0, exp0.Init(geom->shape, TopAbs_COMPSOLID); exp0.More(); exp0.Next()) cnt++; + (*testout) << "COMPSOLID: " << cnt << endl; + + for (cnt = 0, exp0.Init(geom->shape, TopAbs_SOLID); exp0.More(); exp0.Next()) cnt++; + (*testout) << "SOLID : " << cnt << endl; + + for (cnt = 0, exp0.Init(geom->shape, TopAbs_SHELL); exp0.More(); exp0.Next()) cnt++; + (*testout) << "SHELL : " << cnt << endl; + + for (cnt = 0, exp0.Init(geom->shape, TopAbs_FACE); exp0.More(); exp0.Next()) cnt++; + (*testout) << "FACE : " << cnt << endl; + + for (cnt = 0, exp0.Init(geom->shape, TopAbs_WIRE); exp0.More(); exp0.Next()) cnt++; + (*testout) << "WIRE : " << cnt << endl; + + for (cnt = 0, exp0.Init(geom->shape, TopAbs_EDGE); exp0.More(); exp0.Next()) cnt++; + (*testout) << "EDGE : " << cnt << endl; + + for (cnt = 0, exp0.Init(geom->shape, TopAbs_VERTEX); exp0.More(); exp0.Next()) cnt++; + (*testout) << "VERTEX : " << cnt << endl; +} + + +void HealGeometry (OCCGeometry * geom) +{ + TopExp_Explorer exp0; + int cnt; + + + for (cnt = 0, exp0.Init(geom->shape, TopAbs_SOLID); exp0.More(); exp0.Next()) cnt++; + if (cnt == 0) + { + cout << "OCC: Geometry file invalid! No solids. Generating one common solid" << endl; + + BRepOffsetAPI_Sewing sewedObj; + for (exp0.Init(geom->shape, TopAbs_FACE); exp0.More(); exp0.Next()) + sewedObj.Add (TopoDS::Face(exp0.Current())); + sewedObj.Perform(); + + BRepBuilderAPI_MakeSolid ms; + for (exp0.Init(sewedObj.SewedShape(), TopAbs_SHELL); exp0.More(); exp0.Next()) + ms.Add (TopoDS::Shell(exp0.Current())); + + geom->shape = ms; + } +} + + +OCCGeometry * LoadOCC_IGES (const char * filename) +{ + OCCGeometry * occgeo; + occgeo = new OCCGeometry; + + IGESControl_Reader reader; + Standard_Integer stat = reader.LoadFile((char*)filename); + reader.TransferRoots (Standard_False); // Tranlate IGES -> OCC + occgeo->shape = reader.OneShape(); + occgeo->changed = 1; + PrintContents (occgeo); + HealGeometry (occgeo); + occgeo->BuildFMap(); + return occgeo; +} + +OCCGeometry * LoadOCC_STEP (const char * filename) +{ + OCCGeometry * occgeo; + occgeo = new OCCGeometry; + + STEPControl_Reader reader; + Standard_Integer stat = reader.ReadFile((char*)filename); + Standard_Integer nb = reader.NbRootsForTransfer(); + reader.TransferRoots (); // Tranlate STEP -> OCC + occgeo->shape = reader.OneShape(); + occgeo->changed = 1; + PrintContents (occgeo); + HealGeometry (occgeo); + occgeo->BuildFMap(); + return occgeo; +} + + +} + + +#endif diff --git a/Netgen/libsrc/occ/occgeom.hpp b/Netgen/libsrc/occ/occgeom.hpp new file mode 100644 index 0000000000..99472e71ff --- /dev/null +++ b/Netgen/libsrc/occ/occgeom.hpp @@ -0,0 +1,181 @@ +#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 "TopExp_Explorer.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_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 "IGESControl_Reader.hxx" +#include "STEPControl_Reader.hxx" +#include "TopoDS_Shape.hxx" +#include "TopoDS_Face.hxx" + + + +namespace netgen +{ + +#include "occmeshsurf.hpp" + + +class OCCGeometry +{ +public: + TopoDS_Shape shape; + TopTools_IndexedMapOfShape fmap, emap, vmap; + double maxsize; + + bool changed; + + + OCCGeometry() + { + fmap.Clear(); + emap.Clear(); + vmap.Clear(); + } + + + void BuildFMap() + { + TopExp_Explorer exp0, exp1, exp2, exp3; + maxsize = 0; + + /* + for (exp3.Init(shape, TopAbs_EDGE); exp3.More(); exp3.Next()) + { + TopoDS_Edge edge = TopoDS::Edge(exp3.Current()); + (*testout) << edge.Orientation() << endl; + if (emap.FindIndex(edge) < 1) + emap.Add (edge); + } + */ + + + for (exp0.Init(shape, TopAbs_SOLID); exp0.More(); exp0.Next()) + for (exp1.Init(exp0.Current(), TopAbs_SHELL); exp1.More(); exp1.Next()) + { + TopoDS_Shape shell = exp1.Current().Composed (exp0.Current().Orientation()); + + for (exp2.Init(shell, TopAbs_FACE); exp2.More(); exp2.Next()) + { + fmap.Add (exp2.Current().Composed(shell.Orientation())); + + for (exp3.Init(exp2.Current(), TopAbs_EDGE); exp3.More(); exp3.Next()) + { + TopoDS_Edge edge = TopoDS::Edge(exp3.Current()); + if (emap.FindIndex(edge) < 1) + emap.Add (edge); + /* + else + { + cout << edge.Orientation() << " = " << emap(emap.FindIndex(edge)).Orientation() << endl; + } + */ + } + + for (exp3.Init(exp2.Current(), TopAbs_VERTEX); exp3.More(); exp3.Next()) + { + TopoDS_Vertex vertex = TopoDS::Vertex(exp3.Current()); + if (vmap.FindIndex(vertex) < 1) + { + vmap.Add (vertex); + + gp_Pnt p = BRep_Tool::Pnt(vertex); + maxsize = max (maxsize, fabs(p.X())); + maxsize = max (maxsize, fabs(p.Y())); + maxsize = max (maxsize, fabs(p.Y())); + } + } + } + } + maxsize *= 2; + } + + + double MaxSize() + { + return maxsize; + } + + + + void 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)); + + GeomAPI_ProjectPointOnSurf proj(pnt, BRep_Tool::Surface(TopoDS::Face(fmap(surfi)))); + pnt = proj.NearestPoint(); + p = Point<3> (pnt.X(), pnt.Y(), pnt.Z()); + } + +}; + + +void PrintContents (OCCGeometry * geom); +void HealGeometry (OCCGeometry * geom); +OCCGeometry * LoadOCC_IGES (const char * filename); +OCCGeometry * LoadOCC_STEP (const char * filename); + +} + +#endif + +#endif diff --git a/Netgen/libsrc/occ/occmeshsurf.cpp b/Netgen/libsrc/occ/occmeshsurf.cpp new file mode 100644 index 0000000000..c8be2c0770 --- /dev/null +++ b/Netgen/libsrc/occ/occmeshsurf.cpp @@ -0,0 +1,387 @@ +#ifdef OCCGEOMETRY + +#include <mystdlib.h> + +#include <occgeom.hpp> +#include <meshing.hpp> + + +namespace netgen +{ +#include "occmeshsurf.hpp" + +void OCCSurface :: GetNormalVector (const Point<3> & p, + const PointGeomInfo & geominfo, + Vec<3> & n) const +{ + gp_Pnt pnt; + gp_Vec 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(); + + if (orient == TopAbs_REVERSED) n = -1*n; +} + + +void OCCSurface :: DefineTangentialPlane (const Point<3> & ap1, + const PointGeomInfo & geominfo1, + const Point<3> & ap2, + const PointGeomInfo & geominfo2) +{ + p1 = ap1; p2 = ap2; + + GetNormalVector (p1, geominfo1, ez); + + ex = p2 - p1; + ex -= (ex * ez) * ez; + ex.Normalize(); + ey = Cross (ez, ex); + + /* + double u, v; + gp_Vec du, dv; + gp_Pnt pnt(ap2(0), ap2(1), ap2(2)); + GeomAPI_ProjectPointOnSurf proj(pnt, occface); + proj.LowerDistanceParameters (u, v); + occface->D1(u, v, pnt, du, dv); + n2 = Cross (Vec<3>(du.X(), du.Y(), du.Z()), + Vec<3>(dv.X(), dv.Y(), dv.Z())); + n2.Normalize(); + if (orient == TopAbs_REVERSED) n2 = -1*n2; + */ + + 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; + +} + + +void OCCSurface :: ToPlane (const Point<3> & p3d, + const PointGeomInfo & geominfo, + Point<2> & pplane, + double h, int & zone) const +{ + 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; + + /* + Vec<3> v = p3d - p1; + Vec<3> n; + GetNormalVector (p3d, geominfo, n); + + if (n * nmid < 0) + zone = -1; + else + { + double nom = h*(n(0)*(ex(1)*ey(2)-ex(2)*ey(1)) + + n(1)*(ex(2)*ey(0)-ex(0)*ey(2)) + + n(2)*(ex(0)*ey(1)-ex(1)*ey(0))); + + pplane(0) = (n(0)*(ey(2)*v(1)-ey(1)*v(2)) + + n(1)*(ey(0)*v(2)-ey(2)*v(0)) + + n(2)*(ey(1)*v(0)-ey(0)*v(1)))/nom; + + pplane(1) = (n(0)*(ex(1)*v(2)-ex(2)*v(1)) + + n(1)*(ex(2)*v(0)-ex(0)*v(2)) + + n(2)*(ex(0)*v(1)-ex(1)*v(0)))/nom; + + zone = 0; + } + */ +} + + +void OCCSurface :: FromPlane (const Point<2> & pplane, + Point<3> & p3d, + PointGeomInfo & gi, + double h) +{ + p3d = p1 + (h * pplane(0)) * ex + (h * pplane(1)) * ey; + Project (p3d, gi); +} + + + +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)); + GeomAPI_ProjectPointOnSurf proj(pnt, occface); + + pnt = proj.NearestPoint(); + proj.LowerDistanceParameters (gi.u, gi.v); + gi.trignum = 1; + + p = Point<3> (pnt.X(), pnt.Y(), pnt.Z()); +} + + +Meshing2OCCSurfaces :: Meshing2OCCSurfaces (const TopoDS_Shape & asurf, + const Box<3> & abb) + : Meshing2(Box3d(abb.PMin(), abb.PMax())), surface(TopoDS::Face(asurf)) +{ + ; +} + + +void Meshing2OCCSurfaces :: DefineTransformation (Point3d & p1, 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, Point3d & p) const +{ + Point<3> hp = p; + geometry.Project (surfind, hp); + p = hp; +} + +void MeshOptimize2dOCCSurfaces :: ProjectPoint2 (INDEX surfind, INDEX surfind2, + Point3d & p) const +{ + TopExp_Explorer exp0, exp1; + int done = 0; + 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 = 1; + double s0, s1; + c = BRep_Tool::Curve(TopoDS::Edge(exp0.Current()), s0, s1); + } + } + + gp_Pnt pnt(p.X(), p.Y(), p.Z()); + GeomAPI_ProjectPointOnCurve proj(pnt, c); + pnt = proj.NearestPoint(); + p.X() = pnt.X(); + p.Y() = pnt.Y(); + p.Z() = pnt.Z(); + +} + +void MeshOptimize2dOCCSurfaces :: +GetNormalVector(INDEX surfind, const Point3d & p, PointGeomInfo & geominfo, Vec3d & 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 Point3d & p, Vec3d & n) const +{ + // static int cnt = 0; + // if (cnt++ % 1000 == 0) cout << "GetNV cnt = " << cnt << endl; + Standard_Real u,v; + + gp_Pnt pnt(p.X(), p.Y(), p.Z()); + + 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); + + 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 Point3d& p) const +{ + Standard_Real u,v; + + gp_Pnt pnt(p.X(), p.Y(), p.Z()); + + 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); + + gi.u = u; + gi.v = v; + return 1; +} + + + + + + +OCCRefinementSurfaces :: OCCRefinementSurfaces (const OCCGeometry & ageometry) + : Refinement(), geometry(ageometry) +{ + ; +} + +OCCRefinementSurfaces :: ~OCCRefinementSurfaces () +{ + ; +} + +void OCCRefinementSurfaces :: +PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi, + const PointGeomInfo & gi1, + const PointGeomInfo & gi2, + Point3d & newp, PointGeomInfo & newgi) +{ + Point<3> hnewp; + hnewp = p1+secpoint*(p2-p1); + + if (surfi > 0) + { + geometry.Project (surfi, hnewp); + newgi.trignum = 1; + } + + newp = hnewp; +} + + +void OCCRefinementSurfaces :: +PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi1, int surfi2, + const EdgePointGeomInfo & ap1, + const EdgePointGeomInfo & ap2, + Point3d & newp, EdgePointGeomInfo & newgi) +{ + 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; +}; + + +void OCCRefinementSurfaces :: ProjectToSurface (Point<3> & p, int surfi) +{ + if (surfi > 0) + geometry.Project (surfi, p); +}; + + + +} + + +#endif diff --git a/Netgen/libsrc/occ/occmeshsurf.hpp b/Netgen/libsrc/occ/occmeshsurf.hpp new file mode 100644 index 0000000000..aa0399ac23 --- /dev/null +++ b/Netgen/libsrc/occ/occmeshsurf.hpp @@ -0,0 +1,175 @@ +#ifdef OCCGEOMETRY + +#ifndef FILE_OCCMESHSURF +#define FILE_OCCMESHSURF + +#include "occgeom.hpp" + +class OCCGeometry; + +class OCCSurface +{ +public: + TopoDS_Face topods_face; + Handle(Geom_Surface) occface; + TopAbs_Orientation orient; + +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; + +public: + OCCSurface (const TopoDS_Face & aface) + { + topods_face = aface; + occface = BRep_Tool::Surface(topods_face); + orient = topods_face.Orientation(); + /* + 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); + +protected: + /// + virtual void DefineTransformation (Point3d & p1, 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, Point3d & p) const; + /// + virtual void ProjectPoint2 (INDEX surfind, INDEX surfind2, Point3d & p) const; + /// + virtual void GetNormalVector(INDEX surfind, const Point3d & p, Vec3d & n) const; + /// + virtual void GetNormalVector(INDEX surfind, const Point3d & p, PointGeomInfo & gi, Vec3d & n) const; + + + virtual int CalcPointGeomInfo(int surfind, PointGeomInfo& gi, const Point3d& p3) const; + +}; + + + +class OCCGeometry; + + +class OCCRefinementSurfaces : public Refinement +{ + const OCCGeometry & geometry; + +public: + OCCRefinementSurfaces (const OCCGeometry & ageometry); + virtual ~OCCRefinementSurfaces (); + + virtual void PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi, + const PointGeomInfo & gi1, + const PointGeomInfo & gi2, + Point3d & newp, PointGeomInfo & newgi); + + virtual void PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi1, int surfi2, + const EdgePointGeomInfo & ap1, + const EdgePointGeomInfo & ap2, + Point3d & newp, EdgePointGeomInfo & newgi); + + virtual void ProjectToSurface (Point<3> & p, int surfi); +}; + + + +#endif + + + +#endif diff --git a/Netgen/libsrc/opti/Makefile b/Netgen/libsrc/opti/Makefile new file mode 100644 index 0000000000..d73441553f --- /dev/null +++ b/Netgen/libsrc/opti/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for optimisation library +# +src = bfgs.cpp linsearch.cpp linopt.cpp +# +lib = opti +libpath = libsrc/opti +# +# +include ../makefile.inc diff --git a/Netgen/libsrc/opti/bfgs.cpp b/Netgen/libsrc/opti/bfgs.cpp new file mode 100644 index 0000000000..31a499a64d --- /dev/null +++ b/Netgen/libsrc/opti/bfgs.cpp @@ -0,0 +1,367 @@ +/***************************************************************************/ +/* */ +/* 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 i, j, k; + int n = a.Height(); + + // (*testout) << "a = " << a << endl; + + l = a; + + for (i = 1; i <= n; i++) + { + for (j = i; j <= n; j++) + { + x = l.Get(i, j); + + for (k = 1; k < i; k++) + x -= l.Get(i, k) * l.Get(j, k) * d.Get(k); + + if (i == j) + { + d.Elem(i) = x; + } + else + { + l.Elem(j, i) = x / d.Get(k); + } + } + } + + for (i = 1; i <= n; i++) + { + l.Elem(i, i) = 1; + for (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); + } +} + +void SolveLDLt (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 = 1; j < i; j++) + val += p.Get(j) * l.Get(i, j); + p.Elem(i) -= val; + } + for (i = 1; i <= n; i++) + p.Elem(i) /= d.Get(i); + + for (i = n; i >= 1; i--) + { + val = 0; + for (j = i+1; j <= n; j++) + val += p.Get(j) * l.Get(j, i); + p.Elem(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 i, j, n; + + n = l.Height(); + + Vector v(n); + double t, told, xi; + + told = 1; + v = u; + + for (j = 1; j <= n; j++) + { + t = told + a * sqr (v.Elem(j)) / d.Get(j); + + if (t <= 0) return 1; + + xi = a * v.Elem(j) / (d.Get(j) * t); + + d.Elem(j) *= t / told; + + for (i = j + 1; i <= n; i++) + { + v.Elem(i) -= v.Elem(j) * l.Elem(i, j); + l.Elem(i, j) += xi * v.Elem(i); + } + + told = t; + } + + return 0; +} + + +double BFGS ( + Vector & x, // i: Startwert + // o: Loesung, falls IFAIL = 0 + const MinFunction & fun, + const OptiParameters & par, + double eps + ) + + +{ + + int i, j, 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 (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 (i = 1; i <= n; i++) + d.Elem(i) = typf/ sqr (typx.Get(i)); // 1; + for (i = 2; i <= n; i++) + for (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); + + + 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 (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 << "update error1" << endl; + ifail = 1; + break; + } + + if (LDLtUpdate (l, d, -1 / a2, bs) != 0) + { + cerr << "update error2" << endl; + ifail = 1; + break; + } + } + + // Calculate stop conditions + + hd = eps * max2 (typf, fabs (f)); + a1crit = 1; + for (i = 1; i <= n; i++) + if ( fabs (g.Elem(i)) * max2 (typx.Elem(i), fabs (x.Elem(i))) > 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/Netgen/libsrc/opti/linopt.cpp b/Netgen/libsrc/opti/linopt.cpp new file mode 100644 index 0000000000..a5d381e6b7 --- /dev/null +++ b/Netgen/libsrc/opti/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.Elem(1) = b.Get(i1); + rs.Elem(2) = b.Get(i2); + rs.Elem(3) = b.Get(i3); + + 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.Elem(1); + for (int hi = 2; hi <= res.Size(); hi++) + if (res.Elem(hi) < rmin) rmin = res.Elem(hi); + + if ( (f < fmin) && rmin >= -1e-8) + { + fmin = f; + x = hx; + } + } + } +} diff --git a/Netgen/libsrc/opti/linsearch.cpp b/Netgen/libsrc/opti/linsearch.cpp new file mode 100644 index 0000000000..c847911dae --- /dev/null +++ b/Netgen/libsrc/opti/linsearch.cpp @@ -0,0 +1,346 @@ +/***************************************************************************/ +/* */ +/* 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 +{ + int n = x.Size(); + int i, j; + + static Vector xr; + static Vector xl; + xr.SetSize(n); + xl.SetSize(n); + + double eps = 1e-6; + double fl, fr; + + for (i = 1; i <= n; i++) + { + xr.Set (1, x); + xl.Set (1, x); + xr.Elem(i) += eps; + xl.Elem(i) -= eps; + + fl = Func (xl); + fr = Func (xr); + + 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 = 1; i <= n; i++) + { + for (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) = + (f11 + f22 - f12 - f21) / (2 * eps * eps); + } + + hx = x; + f = Func(x); + hx.Elem(i) = x.Get(i) + eps; + f11 = Func(hx); + hx.Elem(i) = x.Get(i) - eps; + f22 = Func(hx); + + hesse.Elem(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; + } + + phi1prime = phi0prime; + + // (*testout) << "phi0prime = " << phi0prime << endl; + + // it = 100000l; + it = 0; + + while (it++ <= par.maxit_linsearch) + { + // (*testout) << "alphahat = " << alphahat << endl; + + xneu.Set2 (1, x, alphahat, p); + + // f = fun.FuncGrad (xneu, g); + // f = fun.Func (xneu); + f = fun.FuncDeriv (xneu, p, phihatprime); + + // (*testout) << "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/Netgen/libsrc/opti/opti.hpp b/Netgen/libsrc/opti/opti.hpp new file mode 100644 index 0000000000..5fa0735bd0 --- /dev/null +++ b/Netgen/libsrc/opti/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 + + + + + /** + Solvers 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/Netgen/libsrc/stlgeom/Makefile b/Netgen/libsrc/stlgeom/Makefile new file mode 100644 index 0000000000..007a979cad --- /dev/null +++ b/Netgen/libsrc/stlgeom/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for geometric library +# +src = stlgeom.cpp stltopology.cpp stlgeomchart.cpp stlgeommesh.cpp meshstlsurface.cpp stlline.cpp stltool.cpp +# +lib = stlgeom +libpath = libsrc/stlgeom +# +# +include ../makefile.inc +# diff --git a/Netgen/libsrc/stlgeom/meshstlsurface.cpp b/Netgen/libsrc/stlgeom/meshstlsurface.cpp new file mode 100644 index 0000000000..b912779237 --- /dev/null +++ b/Netgen/libsrc/stlgeom/meshstlsurface.cpp @@ -0,0 +1,1118 @@ +#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, k; + double h; + + h = mparam.maxh; + + // mark edge points: + int ngp = geom.GetNP(); + + cout << "h1(0,0,0) = " << mesh.LocalHFunction().GetH (Point3d (0,0,0)) << endl; + geom.RestrictLocalH(mesh, h); + cout << "h2(0,0,0) = " << mesh.LocalHFunction().GetH (Point3d (0,0,0)) << endl; + + 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 + for (i = 1; i <= meshpoints.Size(); i++) + { + geom.meshpoints.Append(meshpoints.Get(i)); //testing + + int 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.p1 = p1; + seg.p2 = 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.p1); + 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.p2); + 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.p1), mesh.Point(seg.p2)) < 1e-10) + { + (*testout) << "ERROR: Line segment of length 0" << endl; + (*testout) << "pi1, 2 = " << seg.p1 << ", " << seg.p2 << endl; + (*testout) << "p1, 2 = " << mesh.Point(seg.p1) + << ", " << mesh.Point(seg.p2) << endl; + throw NgException ("Line segment of length 0"); + } + + mesh.AddSegment (seg); + + + Segment seg2; + seg2.p1 = p2; + seg2.p2 = 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.p1); + 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.p2); + 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.p1),mesh.Point(seg.p2)); + } + + 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); + } + + 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.p1, seg.p2); + 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.p1, seg.p2); + i2.Sort(); + if (openseght.Used (i2)) + { + // segment will be split + PrintMessage(7,"Split segment ", int(seg.p1), "-", int(seg.p2)); + + 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.p2 = newpi; + nseg1.epgeominfo[1] = newgi; + + nseg2.p1 = newpi; + nseg2.epgeominfo[0] = newgi; + + mesh.LineSegment(i) = nseg1; + mesh.AddSegment (nseg2); + + mesh.RestrictLocalH (Center (mesh.Point(nseg1.p1), + mesh.Point(nseg1.p2)), + Dist (mesh.Point(nseg1.p1), + mesh.Point(nseg1.p2))); + mesh.RestrictLocalH (Center (mesh.Point(nseg2.p1), + mesh.Point(nseg2.p2)), + Dist (mesh.Point(nseg2.p1), + mesh.Point(nseg2.p2))); + } + } + + } + + 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 + mesh.CheckOverlappingBoundary(); + + 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, k; + 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); + + 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.p1, seg.p2, seg.geominfo[0], seg.geominfo[1]); + } + + + PrintMessage(3,"start meshing, trialcnt = ", retrynr); + + /* + (*testout) << "start meshing with h = " << h << endl; + */ + meshing.GenerateMesh (mesh, h, fnr); // face index +#ifdef OPENGL + extern void Render(); + Render(); +#endif + } + + + mesh.CalcSurfacesOfNode(); +} + + + +void STLSurfaceOptimization (STLGeometry & geom, + class Mesh & mesh, + MeshingParameters & mparam) +{ + PrintFnStart("optimize STL Surface"); + + + MeshOptimizeSTLSurface optmesh(geom); + // + + int i, j; + /* + 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 (mparam.elsizeweight); + + PrintMessage(5,"optimize string = ", mparam.optimize2d, " elsizew = ", mparam.elsizeweight); + + for (i = 1; i <= mparam.optsteps2d; i++) + for (j = 1; j <= strlen(mparam.optimize2d); j++) + { + if (multithread.terminate) + break; + + mesh.CalcSurfacesOfNode(); + switch (mparam.optimize2d[j-1]) + { + case 's': + { + optmesh.EdgeSwapping (mesh, 0); + break; + } + case 'S': + { + optmesh.EdgeSwapping (mesh, 1); + break; + } + case 'm': + { + optmesh.ImproveMesh(mesh); + break; + } + case 'c': + { + optmesh.CombineImprove (mesh); + break; + } + } + } + + geom.surfaceoptimized = 1; + + mesh.Compress(); + mesh.CalcSurfacesOfNode(); + + +} + + + +MeshingSTLSurface :: MeshingSTLSurface (STLGeometry & ageom) + : Meshing2(Box3d (ageom.GetBoundingBox().PMin(), + ageom.GetBoundingBox().PMax())), geom(ageom) +{ + ; +} + +void MeshingSTLSurface :: DefineTransformation (Point3d & p1, 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 Point3d & p, + const PointGeomInfo & gi) +{ + // (*testout) << "sel char: " << gi.trignum << endl; + + geom.SelectChartOfTriangle (gi.trignum); + // geom.SelectChartOfPoint (p); +} + + +void MeshOptimizeSTLSurface :: ProjectPoint (INDEX surfind, Point3d & p) const +{ + Point<3> hp = p; + if (!geom.Project (hp)) + { + PrintMessage(7,"project failed"); + + if (!geom.ProjectOnWholeSurface(hp)) + { + PrintMessage(7, "project on whole surface failed"); + } + } + p = hp; + // geometry.GetSurface(surfind)->Project (p); +} + +void MeshOptimizeSTLSurface :: ProjectPoint2 (INDEX surfind, INDEX surfind2, Point3d & p) const +{ + /* + ProjectToEdge ( geometry.GetSurface(surfind), + geometry.GetSurface(surfind2), p); + */ +} + +int MeshOptimizeSTLSurface :: CalcPointGeomInfo(PointGeomInfo& gi, const Point3d& p3) const +{ + Point<3> hp = p3; + gi.trignum = geom.Project (hp); + + if (gi.trignum) + { + return 1; + } + + return 0; + +} + +void MeshOptimizeSTLSurface :: GetNormalVector(INDEX surfind, const Point3d & p, Vec3d & 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 Point3d & p1, const Point3d & p2, double secpoint, + int surfi, + const PointGeomInfo & gi1, + const PointGeomInfo & gi2, + Point3d & newp, PointGeomInfo & newgi) +{ + 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 Point3d & p1, const Point3d & p2, double secpoint, + int surfi1, int surfi2, + const EdgePointGeomInfo & gi1, + const EdgePointGeomInfo & gi2, + Point3d & newp, EdgePointGeomInfo & newgi) +{ + /* + (*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) +{ + cout << "RefinementSTLGeometry :: ProjectToSurface not implemented!" << endl; +}; + + +} diff --git a/Netgen/libsrc/stlgeom/meshstlsurface.hpp b/Netgen/libsrc/stlgeom/meshstlsurface.hpp new file mode 100644 index 0000000000..99d2918fd1 --- /dev/null +++ b/Netgen/libsrc/stlgeom/meshstlsurface.hpp @@ -0,0 +1,120 @@ +#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); + +protected: + /// + virtual void DefineTransformation (Point3d & p1, 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 Point3d & p, + const PointGeomInfo & gi); + /// + virtual void ProjectPoint (INDEX surfind, Point3d & p) const; + /// + virtual void ProjectPoint2 (INDEX surfind, INDEX surfind2, Point3d & p) const; + /// + virtual int CalcPointGeomInfo(PointGeomInfo& gi, const Point3d& p3) const; + /// + virtual void GetNormalVector(INDEX surfind, const Point3d & p, Vec3d & n) const; +}; + + + + +class RefinementSTLGeometry : public Refinement +{ + const STLGeometry & geom; + +public: + RefinementSTLGeometry (const STLGeometry & ageom); + virtual ~RefinementSTLGeometry (); + + virtual void PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi, + const PointGeomInfo & gi1, + const PointGeomInfo & gi2, + Point3d & newp, PointGeomInfo & newgi); + + virtual void PointBetween (const Point3d & p1, const Point3d & p2, double secpoint, + int surfi1, int surfi2, + const EdgePointGeomInfo & ap1, + const EdgePointGeomInfo & ap2, + Point3d & newp, EdgePointGeomInfo & newgi); + + virtual void ProjectToSurface (Point<3> & p, int surfi); +}; + + + +#endif + diff --git a/Netgen/libsrc/stlgeom/stlgeom.cpp b/Netgen/libsrc/stlgeom/stlgeom.cpp new file mode 100644 index 0000000000..d28ac37ff5 --- /dev/null +++ b/Netgen/libsrc/stlgeom/stlgeom.cpp @@ -0,0 +1,3477 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <gprim.hpp> + +#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(); + + int i; + mesh.ClearFaceDescriptors(); + for (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(), edgedata(*this), selectedmultiedge() +{ + 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() +{ + ; +} + +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 p1,p2; + 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)), p1, p2); + if (!IsEdge(p1,p2)) + { + 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.Elem(k+1) = 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.Elem(k+1) = 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.Get(1), sol.Get(2), sol.Get(3)); + 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 p1, int p2) +{ + STLEdge e(p1,p2); + e.SetLeftTrig(GetLeftTrig(p1,p2)); + e.SetRightTrig(GetRightTrig(p1,p2)); + return edges.Append(e); +} + +void STLGeometry :: STLDoctorConfirmEdge() +{ + StoreEdgeData(); + if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig()) + { + if (stldoctor.selectmode == 1) + { + int p1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); + int p2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); + edgedata.Elem(edgedata.GetEdgeNum(p1,p2)).SetStatus (ED_CONFIRMED); + } + else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4) + { + int i; + for (i = 1; i <= selectedmultiedge.Size(); i++) + { + int p1 = selectedmultiedge.Get(i).i1; + int p2 = selectedmultiedge.Get(i).i2; + edgedata.Elem(edgedata.GetEdgeNum(p1,p2)).SetStatus (ED_CONFIRMED); + } + } + } +} + +void STLGeometry :: STLDoctorCandidateEdge() +{ + StoreEdgeData(); + if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig()) + { + if (stldoctor.selectmode == 1) + { + int p1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); + int p2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); + edgedata.Elem(edgedata.GetEdgeNum(p1,p2)).SetStatus (ED_CANDIDATE); + } + else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4) + { + int i; + for (i = 1; i <= selectedmultiedge.Size(); i++) + { + int p1 = selectedmultiedge.Get(i).i1; + int p2 = selectedmultiedge.Get(i).i2; + edgedata.Elem(edgedata.GetEdgeNum(p1,p2)).SetStatus (ED_CANDIDATE); + } + } + } +} + +void STLGeometry :: STLDoctorExcludeEdge() +{ + StoreEdgeData(); + if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig()) + { + if (stldoctor.selectmode == 1) + { + int p1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); + int p2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); + edgedata.Elem(edgedata.GetEdgeNum(p1,p2)).SetStatus(ED_EXCLUDED); + } + else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4) + { + int i; + for (i = 1; i <= selectedmultiedge.Size(); i++) + { + int p1 = selectedmultiedge.Get(i).i1; + int p2 = selectedmultiedge.Get(i).i2; + edgedata.Elem(edgedata.GetEdgeNum(p1,p2)).SetStatus(ED_EXCLUDED); + } + } + } +} + +void STLGeometry :: STLDoctorUndefinedEdge() +{ + StoreEdgeData(); + if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig()) + { + if (stldoctor.selectmode == 1) + { + int p1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); + int p2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); + edgedata.Elem(edgedata.GetEdgeNum(p1,p2)).SetStatus(ED_UNDEFINED); + } + else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4) + { + int i; + for (i = 1; i <= selectedmultiedge.Size(); i++) + { + int p1 = selectedmultiedge.Get(i).i1; + int p2 = selectedmultiedge.Get(i).i2; + edgedata.Elem(edgedata.GetEdgeNum(p1,p2)).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 pointtree (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); + pointtree.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); + + pointtree.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); + + int nodenr; + 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 pointtree (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; + pointtree.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); + + pointtree.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 p1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); + int p2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); + if (!IsExternalEdge(p1,p2)) {AddExternalEdge(p1,p2);} + } +} + +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 p1 = l->PNum(j); + int p2 = l->PNum(j+1); + + if (!IsExternalEdge(p1,p2)) {AddExternalEdge(p1,p2);} + } + } + } +} + +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 p1 = l->PNum(j); + int p2 = l->PNum(j+1); + + if (!IsExternalEdge(p1,p2)) {AddExternalEdge(p1,p2);} + } + } + } +} + +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 p1 = l->PNum(j); + int p2 = l->PNum(j+1); + + if (!IsExternalEdge(p1,p2)) {AddExternalEdge(p1,p2);} + } + } + } +} + +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 p1 = l->PNum(j); + int p2 = l->PNum(j+1); + + if (IsExternalEdge(p1,p2)) {DeleteExternalEdge(p1,p2);} + } + } + } +} + +void STLGeometry :: AddExternalEdgesFromGeomLine() +{ + StoreExternalEdges(); + if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT()) + { + int p1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); + int p2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); + + if (IsEdge(p1,p2)) + { + int edgenum = IsEdgeNum(p1,p2); + if (!IsExternalEdge(p1,p2)) {AddExternalEdge(p1,p2);} + + int noend = 1; + int startp = p1; + 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 = p2; + 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 p1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); + int p2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); + if (IsExternalEdge(p1,p2)) {DeleteExternalEdge(p1,p2);} + } +} + +void STLGeometry :: DeleteExternalEdgeInVicinity() +{ + StoreExternalEdges(); + if (!stldoctor.showvicinity || vicinity.Size() != GetNT()) {return;} + + int i, j, k, p1, p2; + + for (i = 1; i <= GetNT(); i++) + { + if (vicinity.Elem(i)) + { + for (j = 1; j <= 3; j++) + { + p1 = GetTriangle(i).PNum(j); + p2 = GetTriangle(i).PNumMod(j+1); + + if (IsExternalEdge(p1,p2)) + { + DeleteExternalEdge(p1,p2); + } + } + } + } +} + +void STLGeometry :: BuildExternalEdgesFromEdges() +{ + StoreExternalEdges(); + + if (GetNE() == 0) {PrintWarning("Edges possibly not generated!");} + + int i, p1, p2; + externaledges.SetSize(0); + + for (i = 1; i <= GetNE(); i++) + { + STLEdge e = GetEdge(i); + AddExternalEdge(e.PNum(1), e.PNum(2)); + } + +} + + +void STLGeometry :: AddExternalEdge(int p1, int p2) +{ + externaledges.Append(twoint(p1,p2)); +} + +void STLGeometry :: DeleteExternalEdge(int p1, int p2) +{ + + int i; + int found = 0; + for (i = 1; i <= NOExternalEdges(); i++) + { + if ((GetExternalEdge(i).i1 == p1 && GetExternalEdge(i).i2 == p2) || + (GetExternalEdge(i).i1 == p2 && GetExternalEdge(i).i2 == p1)) {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 p1, int p2) +{ + int i; + for (i = 1; i <= NOExternalEdges(); i++) + { + if ((GetExternalEdge(i).i1 == p1 && GetExternalEdge(i).i2 == p2) || + (GetExternalEdge(i).i1 == p2 && GetExternalEdge(i).i2 == p1)) {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& p1 = GetPoint(tr.PNum(1)); + const Point3d& p2 = GetPoint(tr.PNum(2)); + const Point3d& p3 = GetPoint(tr.PNum(3)); + + Vec3d normal = Cross (p2-p1, p3-p1); + + 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) + { + int i, m; + Point<3> p1, p2; + for (i = 1; i <= n; i++) + { + fin >> p1(0); fin >> p1(1); fin >> p1(2); + fin >> p2(0); fin >> p2(1); fin >> p2(2); + AddMarkedSeg(p1,p2); + } + } +} + +void STLGeometry :: SaveMarkedTrigs() +{ + PrintFnStart("save marked trigs to file 'markedtrigs.ng'"); + ofstream fout("markedtrigs.ng"); + + int n = GetNT(); + fout << n << endl; + + int i, m; + for (i = 1; i <= n; i++) + { + fout << IsMarkedTrig(i) << "\n"; + } + + n = GetNMarkedSegs(); + fout << n << endl; + + Point<3> p1,p2; + for (i = 1; i <= n; i++) + { + GetMarkedSeg(i,p1,p2); + fout << p1(0) << " " << p1(1) << " " << p1(2) << " "; + fout << p2(0) << " " << p2(1) << " " << p2(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 p1, p2; + for (j = 1; j <= NONeighbourTrigs(i); j++) + { + GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), p1, p2); + + if (!IsEdge(p1,p2) && 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 p1, p2; + for (i = 1; i <= GetNT(); i++) + { + found = 0; + for (j = 1; j <= NONeighbourTrigs(i); j++) + { + GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), p1, p2); + + if (!IsEdge(p1,p2)) + { + 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 p1, p2; + + 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)),p1,p2); + if (Dist(GetPoint(p1),GetPoint(p2)) >= maxlen) + { + foundtrig = NeighbourTrig(i,j); + maxlen = Dist(GetPoint(p1),GetPoint(p2)); + } + } + } + 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, j, 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 Point3d *trip1[3], *trip2[3]; + Point3d 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 p1, int p2) +{ + int i,j; + for (i = 1; i <= GetNEPP(p1); i++) + { + for (j = 1; j <= GetNEPP(p2); j++) + { + if (GetEdgePP(p1,i) == GetEdgePP(p2,j)) {return 1;} + } + } + return 0; +} + +int STLGeometry :: IsEdgeNum(int p1, int p2) +{ + int i,j; + for (i = 1; i <= GetNEPP(p1); i++) + { + for (j = 1; j <= GetNEPP(p2); j++) + { + if (GetEdgePP(p1,i) == GetEdgePP(p2,j)) {return GetEdgePP(p1,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; + double ang; + 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"); + + double ang; + int i; + int t1,t2; + + 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, j; + 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, p1, p2; + 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),p1,p2); + AddEdge(p1,p2); + 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; + int edgecnt = 0; + int found; + int rev; //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 p1, p2; + line->GetSeg(ii,p1,p2); + // (*mycout) << "SEG " << p1 << " - " << p2 << endl; + } + } + + PopStatus(); +} + +int STLGeometry :: GetNOBodys() +{ + int markedtrigs = 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 (markedtrigs < 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++; + markedtrigs++; + bodynum.Elem(starttrig) = bodycnt; + todolist.Append(starttrig); + int p1, p2; + + 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; + markedtrigs++; + } + } + } + + 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 markedtrigs = 0; + int starttrig; + int laststarttrig = 1; + int i, k, nnt; + facecnt = 0; + + + for (i = 1; i <= GetNT(); i++) + GetTriangle(i).SetFaceNum(0); + + + while (markedtrigs < 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++; + markedtrigs++; + GetTriangle(starttrig).SetFaceNum(facecnt); + todolist.Append(starttrig); + int p1, p2; + + 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,p1,p2); + if (!IsEdge(p1,p2)) + { + nextlist.Append(nnt); + nt.SetFaceNum(facecnt); + markedtrigs++; + } + } + } + } + + 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); + + Vec3d ng1 = trig.GeomNormal(points); + ng1 /= (ng1.Length() + 1e-24); + + for (j = 1; j <= 3; j++) + { + int nbt = NeighbourTrig (i, j); + + Vec3d 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 p1, p2, 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, p1, p2); + if (IsEdge(p1,p2)) 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, p1, p2); + if (IsEdge(p1,p2)) 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(p1,p2); + se.SetLeftTrig(tn1); + se.SetRightTrig(tn2); + int edgenum = AddEdge(se); + AddEdgePP(p1,edgenum); + AddEdgePP(p2,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, p1, p2); + if (IsEdge(p1,p2)) 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, p1, p2); + if (IsEdge(p1,p2)) 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(p1,p2); + se.SetLeftTrig(tn1); + se.SetRightTrig(tn2); + int edgenum = AddEdge(se); + AddEdgePP(p1,edgenum); + AddEdgePP(p2,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)), p1, p2); + if (IsEdge(p1,p2)) {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, p1, p2, locindex1, locindex2; + + //(*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, p1, p2); + if (p2 == p) {Swap(p1,p2);} + if (p1 != p) {PrintSysError("In GetSortedTrianglesAroundPoint!!!");} + + for (j = 1; j <= 3; j++) + { + if (at.PNum(j) == p1) {locindex1 = j;}; + if (at.PNum(j) == p2) {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; + + int np = GetNP(); + double maxerr0, maxerr; + + for (i = 1; i <= np; 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/Netgen/libsrc/stlgeom/stlgeom.hpp b/Netgen/libsrc/stlgeom/stlgeom.hpp new file mode 100644 index 0000000000..2ac1cd1e36 --- /dev/null +++ b/Netgen/libsrc/stlgeom/stlgeom.hpp @@ -0,0 +1,450 @@ +#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 <gprim.hpp> +#include <meshing.hpp> + + + +namespace netgen +{ + extern int IsInArray(int n, const ARRAY<int>& ia); + extern int AddIfNotExists(ARRAY<int>& list, int x); + + +#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 + { + // 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(); + + + + 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> & p1, const Point<3> & p2) + { + markedsegs.Append(p1);markedsegs.Append(p2); + } + + void GetMarkedSeg(int i, Point<3> & p1, Point<3> & p2) + { + p1=markedsegs.Get(i*2-1); + p2=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; + }; + + +#include "meshstlsurface.hpp" + + + extern int STLMeshingDummy (STLGeometry* stlgeometry, Mesh*& mesh, + int perfstepsstart, int perfstepsend, char* optstring); + + +} +#endif diff --git a/Netgen/libsrc/stlgeom/stlgeomchart.cpp b/Netgen/libsrc/stlgeom/stlgeomchart.cpp new file mode 100644 index 0000000000..6e3fe8b2d3 --- /dev/null +++ b/Netgen/libsrc/stlgeom/stlgeomchart.cpp @@ -0,0 +1,801 @@ +//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(class Mesh & mesh) +{ + + double h, h2; + + h = mparam.maxh; + + + PushStatusF("Make Atlas"); + + int i,j,k,l,m,ctl; + + 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 mindist, 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++) + { + int j; + //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 j,k, 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); + + + 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; + STLTriangle tt; + + 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 addedges = 0; + int p1, p2, 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; + + int worked = 0; + 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, p1, p2); + if (IsEdge(p1,p2)) 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, p1, p2); + if (IsEdge(p1,p2)) 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/Netgen/libsrc/stlgeom/stlgeommesh.cpp b/Netgen/libsrc/stlgeom/stlgeommesh.cpp new file mode 100644 index 0000000000..37656495e7 --- /dev/null +++ b/Netgen/libsrc/stlgeom/stlgeommesh.cpp @@ -0,0 +1,1591 @@ +//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> & p1, int t1, + const Point<3> & p2, 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(p1,pbtw); + + edgepoints.Add1(edgecnt,pbtw); + edgepointdists.Add1(edgecnt,Dist(pbtw,p1)); + edgepointorigines.Add1(edgecnt,0); + edgepointoriginps.Add1(edgecnt,0); + } + } + + int finished = 0; + int endpointorigine = 0; + int endpointoriginp = 0; + double endpointmindist = 1E50; + + int cnt = 0; + 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; + int 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; + for (m = 1; m <= divisions; m++) + { + const Point3d& p = edgepoints.Get(en,m); + if (Dist(p2,p) + edgepointdists.Get(en,m) < mindist) + {mindist = Dist(p2,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(p2); + 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(p1); + + 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(p1,p2);} + + 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 > & points, + ARRAY<Point3d > & points3d, + ARRAY<INDEX_2> & lines, double h) +{ + int i, j; + twoint seg, newseg; + int zone; + int psize; + 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); + points.Append (p2d); + + lpi = points.Size(); + ha_points.Elem(pi) = lpi; + } + else + lpi = ha_points.Get(pi); + + i2.I(j) = lpi; + } + lines.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, j, k; + + 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; + int ci = 1; + 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, k; + 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, k; + 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; + + //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 p1,p2,p3,p4; + Point<3> p1p, p2p, p3p, p4p; + double mindist, ang; + Vec<3> n, ntn; + double rzyl, sinang, 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,p1,p2,p3); + + //checken, ob p1-p2 eine Kante sind + if (IsEdge(p1,p2)) continue; + + p4 = trig.PNum(1) + trig.PNum(2) + trig.PNum(3) - p1 - p2; + + p1p = GetPoint(p1); p2p = GetPoint(p2); + 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(p1) = min2(minh.Elem(p1),localh); + minh.Elem(p2) = min2(minh.Elem(p2),localh); + } + + //if (localh < 0.2) {localh = 0.2;} + mesh.RestrictLocalHLine(p1p, p2p, localh); + } + + } + } + PrintMessage(7, "done\nATLAS H: nmin local h=", mincalch); + PrintMessage(7, "ATLAS H: max local h=", maxcalch); + PrintMessage(7, "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 p1,p2,p3,p4; + Point3d p1p, p2p, p3p, p4p; + double mindist, ang; + Vec3d n, ntn; + double rzyl, sinang, 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,p1,p2,p3); + + //checken, ob p1-p2 eine Kante sind + if (IsEdge(p1,p2)) continue; + + p4 = trig.PNum(1) + trig.PNum(2) + trig.PNum(3) - p1 - p2; + + p1p = GetPoint(p1); p2p = GetPoint(p2); + 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(p1) = min2(minh.Elem(p1),localh); + minh.Elem(p2) = min2(minh.Elem(p2),localh); + } + + //if (localh < 0.2) {localh = 0.2;} + mesh.RestrictLocalHLine(p1p, p2p, localh); + + 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, p3p2; + double mindist = 1E50; + + PrintMessage(7,"build search tree..."); + Box3dTree* searchtree = 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); + + searchtree->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); + searchtree->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 ecnt = 0; + int lp1, lp2; + int i; + Vec3d v1,v2; + double rzyl; + double mincalch = 1E50; + double 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& p1 = GetPoint(GetLine(i)->StartP()); + const Point3d& p2 = GetPoint(GetLine(i)->EndP()); + + if (l != 0) + { + minhl = min2(minhl,l*linefact); + + mesh.RestrictLocalH(p1, l*linefact); + mesh.RestrictLocalH(p2, 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 & p1 = plimes1.Get(j); + double boxs = mesh.GetH (plimes1.Get(j)) * limessafety; + + Point3d pmin = p1 - Vec3d (boxs, boxs, boxs); + Point3d pmax = p1 + 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 & p1 = plimes1.Get(j); + double his = mesh.GetH (plimes1.Get(j)); + + double xmin = p1.X() - his * limessafety; + double xmax = p1.X() + his * limessafety; + double ymin = p1.Y() - his * limessafety; + double ymax = p1.Y() + his * limessafety; + double zmin = p1.Z() - his * limessafety; + double zmax = p1.Z() + his * limessafety; + + for (k = 1; k <= plimes2.Size(); k++) + { + const Point3d & p2 = plimes2.Get(k); + if (p2.X() >= xmin && p2.X() <= xmax && + p2.Y() >= ymin && p2.Y() <= ymax && + p2.Z() >= zmin && p2.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;} + } + } + } + +} + + +//void * STLMeshingDummy (void *) +int STLMeshingDummy (STLGeometry* stlgeometry, Mesh*& mesh, + int perfstepsstart, int perfstepsend, char* optstring) +{ + if (perfstepsstart > perfstepsend) return 0; + + multithread.terminate = 0; + int success = 1; + //int trialcntouter = 0; + + if (perfstepsstart <= MESHCONST_MESHEDGES) + { + + mesh = new Mesh(); + mesh -> SetGlobalH (mparam.maxh); + mesh -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10), + stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10), + mparam.grading); + + int i; + 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 -> CalcLocalHFromSurfaceCurvature (stlparam.resthsurfmeshcurvfac); + mparam.optimize2d = "cmsmSm"; + STLSurfaceOptimization (*stlgeometry, *mesh, mparam); +#ifdef STAT_STREAM + (*statout) << GetTime() << " & "; +#endif + +#ifdef OPENGL + extern void Render(); + Render(); +#endif + } + 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 -> CalcLocalH (); + } + + + 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, NULL); + +#ifdef STAT_STREAM + (*statout) << GetTime() << " & " << endl; + (*statout) << mesh->GetNE() << " & " << endl + << mesh->GetNP() << " " << '\\' << '\\' << " \\" << "hline" << endl; +#endif + +#ifdef OPENGL + extern void Render(); + Render(); +#endif + + } + } + + + return 0; +} + + + +} diff --git a/Netgen/libsrc/stlgeom/stlline.cpp b/Netgen/libsrc/stlgeom/stlline.cpp new file mode 100644 index 0000000000..792b1fcd43 --- /dev/null +++ b/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, 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 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, en; + int j, i, k; + int oldend; + int newend = 1; + int pnew, ennew; + + 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/Netgen/libsrc/stlgeom/stlline.hpp b/Netgen/libsrc/stlgeom/stlline.hpp new file mode 100644 index 0000000000..70393ca060 --- /dev/null +++ b/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/Netgen/libsrc/stlgeom/stltool.cpp b/Netgen/libsrc/stlgeom/stltool.cpp new file mode 100644 index 0000000000..9513904bfa --- /dev/null +++ b/Netgen/libsrc/stlgeom/stltool.cpp @@ -0,0 +1,1288 @@ +#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; + double nearest = 1E50; + int fi = 0; + int j; + + for (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 i, 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/Netgen/libsrc/stlgeom/stltool.hpp b/Netgen/libsrc/stlgeom/stltool.hpp new file mode 100644 index 0000000000..278a7ce4ee --- /dev/null +++ b/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/Netgen/libsrc/stlgeom/stltopology.cpp b/Netgen/libsrc/stlgeom/stltopology.cpp new file mode 100644 index 0000000000..1d5315fbec --- /dev/null +++ b/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), + neighbourtrigs(), trigsperpoint() +{ + ; +} + +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) +{ + 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) +{ + 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) +{ + 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) +{ + int 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; + + int 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, j, 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; + 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> & trias) const +{ + if (searchtree) + + searchtree -> GetIntersecting (box.PMin(), box.PMax(), trias); + + else + { + int i; + Box<3> box1 = box; + box1.Increase (1e-4); + + trias.SetSize(0); + + int nt = GetNT(); + for (i = 1; i <= nt; i++) + { + if (box1.Intersect (GetTriangle(i).box)) + { + trias.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 j = 0,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/Netgen/libsrc/stlgeom/stltopology.hpp b/Netgen/libsrc/stlgeom/stltopology.hpp new file mode 100644 index 0000000000..80e5a68178 --- /dev/null +++ b/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); + void SaveBinary (const char* filename, const char* aname); + void SaveSTLE (const char * filename); // 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/Netgen/libsrc/visualization/Makefile b/Netgen/libsrc/visualization/Makefile new file mode 100644 index 0000000000..f8e80916e9 --- /dev/null +++ b/Netgen/libsrc/visualization/Makefile @@ -0,0 +1,13 @@ +# +# Makefile for visualization library +# +src = stlmeshing.cpp mvdraw.cpp vscsg.cpp vsmesh.cpp vssolution.cpp meshdoc.cpp +# +lib = vis +libpath = libsrc/visualization +# +# +include ../makefile.inc +# + + diff --git a/Netgen/libsrc/visualization/meshdoc.cpp b/Netgen/libsrc/visualization/meshdoc.cpp new file mode 100644 index 0000000000..4c0f064c05 --- /dev/null +++ b/Netgen/libsrc/visualization/meshdoc.cpp @@ -0,0 +1,615 @@ +#include <mystdlib.h> + +#include <meshing.hpp> + +#include "incvis.hpp" + + + +namespace netgen +{ +#include "mvdraw.hpp" +#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 () +{ + int i, j, k; + + 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, k; + + + 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); + + static float matcol0[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + static float matcol1[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + static float matcolsel[] = { 1.0f, 0.0f, 0.0f, 1.0f }; + static float matcolnosel[] = { 0.0f, 1.0f, 0.0f, 1.0f }; + + 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.p1); + const Point3d & p2 = mesh->Point(seg.p2); + + if (edgedist.Get(seg.p1) <= markedgedist && + edgedist.Get(seg.p2) <= 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, 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); + + 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.p1 == selpoint && seg.p2 == selpoint2 || + seg.p2 == selpoint && seg.p1 == 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.p1), edgedist.Get(seg.p2)); + edist++; + + if (edgedist.Get(seg.p1) > edist) + { + edgedist.Elem(seg.p1) = edist; + changed = 1; + } + if (edgedist.Get(seg.p2) > edist) + { + edgedist.Elem(seg.p2) = edist; + changed = 1; + } + } + } + while (changed); +} + +int VisualSceneMeshDoctor :: IsSegmentMarked (int segnr) const +{ + const Segment & seg = mesh->LineSegment(segnr); + return (edgedist.Get(seg.p1) <= markedgedist && + edgedist.Get(seg.p2) <= markedgedist); +} +} diff --git a/Netgen/libsrc/visualization/meshdoc.hpp b/Netgen/libsrc/visualization/meshdoc.hpp new file mode 100644 index 0000000000..5cc11aef78 --- /dev/null +++ b/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/Netgen/libsrc/visualization/mvdraw.cpp b/Netgen/libsrc/visualization/mvdraw.cpp new file mode 100644 index 0000000000..c166e5aac3 --- /dev/null +++ b/Netgen/libsrc/visualization/mvdraw.cpp @@ -0,0 +1,1540 @@ +#include <mystdlib.h> +#include <myadt.hpp> +#include <meshing.hpp> +#include <csg.hpp> +#include <geometry2d.hpp> +#include <stlgeom.hpp> + +#ifdef OCCGEOMETRY +#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 "BRepMesh.hxx" +#endif + + +#include "incvis.hpp" + + +#ifdef STEP +#include <stepgeom.hpp> +#endif + +namespace netgen +{ + +#include "mvdraw.hpp" + +Point3d VisualScene :: center; +double VisualScene :: rad; +double VisualScene :: backcolor; +GLuint VisualScene :: fontbase = 0; + +// texture for color decoding +GLubyte * VisualScene :: colortexture = NULL; +GLuint VisualScene :: coltexname = 1; +int VisualScene :: ntexcols = -1; + // bool VisualScene :: linear_colors = 1; + +float VisualScene :: lookatmat[16]; +float VisualScene :: transmat[16]; +float VisualScene :: rotmat[16]; +float VisualScene :: centermat[16]; +float VisualScene :: transformationmat[16]; + + + +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"); +}; +VisualizationParameters vispar; + + + +double dist = 0; + // double dist = 6; +// vorher: pnear = 2; +double pnear = 0.1; +double pfar = 10; + + + +extern CSGeometry * geometry; +extern STLGeometry * stlgeometry; +extern SplineGeometry2d * geometry2d; + +#ifdef OCCGEOMETRY +extern OCCGeometry * occgeometry; +#endif + +#ifdef STEP +using STEP_AP203::STEPGeometry; +extern STEPGeometry * stepgeometry; +#endif // STEP +extern AutoPtr<Mesh> mesh; +extern ARRAY<SpecialPoint> specpoints; + +//Tcl_Interp * hinterp; + + +VisualScene :: VisualScene () +{ + changeval = -1; + backcolor = 0; + + + +} + +VisualScene :: ~VisualScene() +{ + ; +} + + +void Render () +{ + multithread.redraw = 1; + // while (multithread.redraw); + // Tcl_Eval (hinterp, ".ndraw render"); +} + +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); + + /* + glPushMatrix(); + // glLoadIdentity(); + glMultMatrixf (transformationmat); + + glBegin(GL_LINES); + glVertex3f (0.0f, 0.0f, 0.0f); + glVertex3f (1.0f, 0.0f, 0.0f); + glVertex3f (0.0f, 0.0f, 0.0f); + glVertex3f (0.0f, 1.0f, 0.0f); + glVertex3f (0.0f, 0.0f, 0.0f); + glVertex3f (0.0f, 0.0f, 1.0f); + glEnd (); + + glPopMatrix(); + */ + + 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 :: 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.95; + GLdouble pvx2 = deltax, pvy2 = -deltay, pvz2 = 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); + glScaled (exp (float (-deltay)/100), + exp (float (-deltay)/100), + exp (float (-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 h, double hmin, double hmax, + int logscale) +{ + double value; + + if (!logscale) + value = (h - hmin) / (hmax - hmin); + else + { + if (hmax <= 0) hmax = 1; + if (hmin <= 0) hmin = 1e-4 * hmax; + value = (log(fabs(h)) - log(hmin)) / (log(hmax) - log(hmin)); + } + + if (!invcolor) + value = 1 - value; + + glTexCoord1f ( 0.999 * value + 0.001); + + if (value > 1) value = 1; + if (value < 0) value = 0; + + value *= 4; + + 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]; + int j; + for (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 i; + + if (ncols < 2) ncols = 2; + ncols = 8; + + if (ntexcols != ncols) + { + if (colortexture) + { + glDeleteTextures (1, &coltexname); + delete colortexture; + } + + ntexcols = ncols; + + colortexture = new GLubyte[4*ncols+4]; + + 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 }, + }; + + for (i = 0; i < ncols; i++) + { + double value = 4.0 * i / (ncols-1); + + int iv = int(value); + double r = value - iv; + + GLdouble col[3]; + int j; + for (j = 0; j < 3; j++) + col[j] = (1-r) * colp[iv][j] + r * colp[iv+1][j]; + + glColor3d (col[0], col[1], col[2]); + + 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); + + + glGenTextures (1, &coltexname); + + + glBindTexture (GL_TEXTURE_1D, coltexname); + + glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexImage1D (GL_TEXTURE_1D, 0, 4, ncols, 0, GL_RGBA, GL_UNSIGNED_BYTE, colortexture); + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + + } + + + glBindTexture (GL_TEXTURE_1D, coltexname); + if (linear) + { + glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_1D, 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); + } +} + + + + +void VisualScene :: DrawColorBar (double minval, double maxval, + int logscale) +{ + int i; + + if (!vispar.drawcolorbar) return; + + CreateTexture (8, 1); + + 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; + + double x; + + glEnable (GL_COLOR_MATERIAL); + glEnable (GL_TEXTURE_1D); + glNormal3d (0, 0, 1); + + glBegin (GL_LINES); + for (x = minx; x <= maxx; x += (maxx - minx) / 1000) + { + 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 (i = 0; i <= 4; i++) + { + 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 (strlen (buf), GL_UNSIGNED_BYTE, buf); + } + + glPopAttrib (); +} + + +void VisualScene :: DrawCoordinateCross () +{ + if (!vispar.drawcoordinatecross) return; + + 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); + + GLfloat textcol[3] = { 1 - backcolor, + 1 - backcolor, + 1 - backcolor }; + glColor3fv (textcol); + + glLineWidth (1.0f); + + float len = 1; + glBegin(GL_LINES); + glVertex3f (0.0f, 0.0f, 0.0f); + glVertex3f (len, 0.0f, 0.0f); + glVertex3f (0.0f, 0.0f, 0.0f); + glVertex3f (0.0f, len, 0.0f); + glVertex3f (0.0f, 0.0f, 0.0f); + glVertex3f (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 (strlen (buf), GL_UNSIGNED_BYTE, buf); + glRasterPos3d (0.0f, len, 0.0f); + sprintf (buf, "y"); + glCallLists (strlen (buf), GL_UNSIGNED_BYTE, buf); + glRasterPos3d (0.0f, 0.0f, len); + sprintf (buf, "z"); + glCallLists (strlen (buf), GL_UNSIGNED_BYTE, buf); + + glPopAttrib (); + glEnable (GL_LIGHTING); + + glMatrixMode (GL_PROJECTION); + glPopMatrix(); + glMatrixMode (GL_MODELVIEW); + glPopMatrix(); +} + + +void VisualScene :: DrawNetgenLogo () +{ + if (!vispar.drawnetgenlogo) return; + + 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 (-6.0, 2.0, 0.0); + // glMultMatrixf (rotmat); + + 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[20]; + + glRasterPos3d (0.0f, 0.0f, 0.0f); + sprintf (buf, "Netgen 4.3.1"); + glCallLists (strlen (buf), GL_UNSIGNED_BYTE, buf); + glPopAttrib (); + + glMatrixMode (GL_PROJECTION); + glPopMatrix(); + glMatrixMode (GL_MODELVIEW); + glPopMatrix(); +} + + + + + + + + +VisualSceneGeometry2d :: VisualSceneGeometry2d () + : VisualScene() +{ + ; +} + +VisualSceneGeometry2d :: ~VisualSceneGeometry2d () +{ + ; +} + + + + + + +void VisualSceneGeometry2d :: DrawScene () +{ + int i, j; + + 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 (i = 1; i <= geometry2d->GetSplines().Size(); i++) + { + geometry2d->GetSplines().Get(i)->GetPoints (20, points); + + glBegin (GL_LINE_STRIP); + for (j = 0; j < points.Size(); j++) + glVertex3f (points[j](0), points[j](1), 0); + glEnd(); + } + + glColor3f (1, 0, 0); + + for (i = 1; i <= geometry2d->GetSplines().Size(); i++) + { + int other = geometry2d->GetSplines().Get(i)->copyfrom; + if (other != -1) + { + geometry2d->GetSplines().Get(i)->GetPoints (6, points); + geometry2d->GetSplines().Get(other)->GetPoints (6, otherpoints); + glBegin (GL_LINES); + for (j = 1; j < 5; j++) + { + glVertex3f (points[j](0), points[j](1), 0); + glVertex3f (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(); +} + + + + + + + + + + +/* *********************** Draw STL Geometry **************** */ + + +VisualSceneSTLGeometry :: VisualSceneSTLGeometry () + : VisualScene() +{ + ; +} + +VisualSceneSTLGeometry :: ~VisualSceneSTLGeometry () +{ + ; +} + +void VisualSceneSTLGeometry :: DrawScene () +{ + int i, j, k; + + 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.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); + + glCallList (trilists.Get(1)); + + glDisable (GL_POLYGON_OFFSET_FILL); + + + int showtrias = vispar.showstltrias; + + if (showtrias) + { + float mat_coll[] = { 0.2, 0.2, 0.2, 1 }; + 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) +{ + int i, j, k; + + // cout << "rebuild stl geometry scene" << endl; + + center = stlgeometry -> GetBoundingBox().Center(); + rad = stlgeometry -> GetBoundingBox().Diam() / 2; + + + CalcTransformationMatrices(); + + for (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 (j = 1; j <= stlgeometry -> GetNT(); j++) + { + const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); + glNormal3f (n.X(), n.Y(), n.Z()); + + for (k = 1; k <= 3; k++) + { + const Point3d & p = + stlgeometry->GetPoint (stlgeometry -> GetTriangle(j).PNum(k)); + glVertex3f (p.X(),p.Y(), p.Z()); + + // int pi = ta.GetTriangle(j).PNum(k); + // glNormal3f (ta.GetNormal (pi).X(), + // ta.GetNormal (pi).Y(), + // ta.GetNormal (pi).Z()); + // glVertex3f (ta.GetPoint(pi).X(), + // ta.GetPoint(pi).Y(), + // ta.GetPoint(pi).Z()); + } + } + glEnd (); + + glEndList (); +} + + + +#ifdef OCCGEOMETRY +/* *********************** Draw OCC Geometry **************** */ + + +VisualSceneOCCGeometry :: VisualSceneOCCGeometry () + : VisualScene() +{ + trilists.SetSize(0); + linelists.SetSize(1); +} + +VisualSceneOCCGeometry :: ~VisualSceneOCCGeometry () +{ + ; +} + +void VisualSceneOCCGeometry :: DrawScene () +{ + int i, j, k; + + + if ( occgeometry->changed ) + { + BuildScene(); + occgeometry -> changed = 0; + } + + 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); + 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); + + glCallList (linelists.Get(1)); + + glDisable (GL_POLYGON_OFFSET_FILL); + + glPopMatrix(); + DrawCoordinateCross (); + DrawNetgenLogo (); + glFinish(); + + glDisable (GL_POLYGON_OFFSET_FILL); + +} + + +void VisualSceneOCCGeometry :: BuildScene (int zoomall) +{ + int i = 0, j, k; + + Box3d box; + + TopExp_Explorer ex, ex_edge; + + for (ex.Init(occgeometry -> shape, TopAbs_VERTEX); ex.More(); ex.Next()) + { + i++; + gp_Pnt p = BRep_Tool::Pnt (TopoDS::Vertex(ex.Current())); + + if (i == 1) + box.SetPoint (Point<3>(p.X(), p.Y(), p.Z())); + else + box.AddPoint (Point<3>(p.X(), p.Y(), p.Z())); + } + + center = box.CalcCenter(); + rad = box.CalcDiam() / 2; + + CalcTransformationMatrices(); + + + linelists.Elem(1) = glGenLists (1); + glNewList (linelists.Last(), GL_COMPILE); + + for (ex_edge.Init(occgeometry -> shape, TopAbs_EDGE); + ex_edge.More(); ex_edge.Next()) + { + if (BRep_Tool::Degenerated(TopoDS::Edge(ex_edge.Current()))) continue; + + glBegin (GL_LINE_STRIP); + + double s0, s1, s; + Handle(Geom_Curve) c = BRep_Tool::Curve(TopoDS::Edge(ex_edge.Current()), s0, s1); + double d = s1-s0; + int i; + + for (i = 0; i<=50; i++) + { + s = s0 + i*d/50; + gp_Pnt p = c->Value (s); + glVertex3f (p.X(),p.Y(), p.Z()); + } + + glEnd (); + } + + // glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); + + glBegin (GL_TRIANGLES); + // int nfaces = occgeometry -> fmap.Extent(); + + i = 0; + + TopExp_Explorer exp0, exp1, exp2, exp3; + + // BRepMesh::Mesh (occgeometry -> shape, occgeometry -> MaxSize()/100); + + for (exp0.Init(occgeometry -> shape, TopAbs_SOLID); exp0.More(); exp0.Next()) + 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())); + + TopLoc_Location loc; + Handle(Geom_Surface) surf = BRep_Tool::Surface (face); + BRepAdaptor_Surface sf(face, Standard_False); + BRepLProp_SLProps prop(sf, 1, 1e-5); + + // BRepMesh::Mesh (face, 1e-3); + (*testout) << "meshing face " << ++i << endl; + { + int edges = 0; + for (exp3.Init (face, TopAbs_EDGE); exp3.More(); exp3.Next()) + { + edges++; + (*testout) << "edge " << edges; + if (BRep_Tool::Degenerated(TopoDS::Edge(exp3.Current()))) + (*testout) << " degenerated"; + (*testout) << endl; + } + } + BRepMesh::Mesh (face, occgeometry -> MaxSize()/100); + (*testout) << "done" << endl; + // cout << "Warning: mvdraw fixed meshing size for visualization" << endl; + // cout << "face " << ++i << endl; + + Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc); + if (!triangulation) continue; + + int ntriangles = triangulation -> NbTriangles(); + // cout << "nbtriangles = " << ntriangles << endl; + for (j = 1; j <= ntriangles; j++) + { + // (*testout) << "drawing trig " << j << "/" << ntriangles << " " << flush; + // cout << "j = " << j << endl; + Poly_Triangle triangle = (triangulation -> Triangles())(j); + for (k = 1; k <= 3; k++) + { + (*testout) << "." << flush; + 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); + + + // surf->D1 (uv.X(), uv.Y(), pnt, du, dv); + // gp_Vec n = du.Crossed(dv).Normalized(); + if (face.Orientation() == TopAbs_REVERSED) n *= -1; + glNormal3f (n.X(), n.Y(), n.Z()); + glVertex3f (pnt.X(), pnt.Y(), pnt.Z()); + } + (*testout) << endl; + } + } + + glEnd (); + + + + glEndList (); + +} + +#endif + + + +#ifdef STEP + +/* *********************** Draw STEP Geometry **************** */ + + +VisualSceneSTEPGeometry :: VisualSceneSTEPGeometry () + : VisualScene () +{ + gllists.SetSize(0); +} + + +VisualSceneSTEPGeometry :: ~VisualSceneSTEPGeometry () +{ + cout << "VisualSceneSTEPGeometry::~VisualSceneSTEPGeometry called " + << "but not implemented" << endl; +} + + +void VisualSceneSTEPGeometry :: BuildScene (int zoomall) +{ + cout << "VisualSceneSTEPGeometry::BuildScene called" << endl; + + const VisualApproximation & visapprox = + stepgeometry->GetVisualApproximation(); + + INDEX i, k, pi; + + Box3d box; + int hasp = 0; + + for (i = 1; i <= visapprox.GetNP(); i++) + { + if (hasp) + box.AddPoint (visapprox.GetPoint(i)); + else + { + hasp = 1; + box.SetPoint (visapprox.GetPoint(i)); + } + } + if (hasp) + { + center = box.CalcCenter(); + rad = box.CalcDiam() / 2; + } + + cout << "center " << center << endl + << "radius " << rad << endl; + + CalcTransformationMatrices(); + + for (i = 1; i <= gllists.Size(); i++) + glDeleteLists (gllists.Elem(i), 1); + gllists.SetSize(0); + + // build list of points + gllists.Append (glGenLists (1)); + glNewList (gllists.Last(), GL_COMPILE); + + glPointSize( 3.0 ); + + glBegin( GL_POINTS ); + for (i = 1; i <= visapprox.GetNP(); i++) + { + const Point3d & p = visapprox.GetPoint(i); + glVertex3f( p.X(), p.Y(), p.Z()); + } + glEnd(); + + glEndList(); + + // build list of segments + gllists.Append (glGenLists (1)); + glNewList (gllists.Last(), GL_COMPILE); + + glLineWidth( 1.0f ); + + glBegin(GL_LINES); + for (i = 1; i <= visapprox.GetNSeg(); i++) + { + for (k = 1; k <= 2; k++) + { + pi = visapprox.GetSegment(i).PNum(k); + glVertex3f(visapprox.GetPoint(pi).X(), + visapprox.GetPoint(pi).Y(), + visapprox.GetPoint(pi).Z()); + } + } + glEnd(); + + glEndList(); +} + + +void VisualSceneSTEPGeometry :: DrawScene () +{ + if (! stepgeometry) + { + cerr << "VisualSceneSTEPGeometry::DrawScene: no STEP geometry" << endl; + return; + } + + const VisualApproximation & visapprox = + stepgeometry -> GetVisualApproximation(); + if (changeval != visapprox.GetNP()) + BuildScene(); + + changeval = visapprox.GetNP(); + + glClearColor(backcolor, backcolor, backcolor, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glMultMatrixf (transformationmat); + + // draw segments +// float mat_coll[] = { 0.2, 0.2, 0.2, 1 }; +// glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_coll); +// glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); + + glEnable (GL_COLOR_MATERIAL); + glColor3f(0.0, 1.0, 0.0); + glCallList (gllists.Get(2)); + glColor3f (1.0, 0.0, 0.0); + glCallList (gllists.Get(1)); + + glPopMatrix(); + glFinish(); +} + +#endif + + + + + + + + + + +VisualSceneSpecPoints :: VisualSceneSpecPoints () + : VisualScene() +{ + ; +} + +VisualSceneSpecPoints :: ~VisualSceneSpecPoints () +{ + ; +} + + +void VisualSceneSpecPoints :: DrawScene () +{ + int i, j, k; + + + 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 (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 (i = 1; i <= mesh->GetNSeg(); i++) + { + const Segment & seg = mesh -> LineSegment (i); + const Point3d p1 = mesh -> Point (seg.p1); + const Point3d p2 = mesh -> Point (seg.p2); + glVertex3d (p1.X(), p1.Y(), p1.Z()); + glVertex3d (p2.X(), p2.Y(), p2.Z()); + } + 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 (i = 1; i <= mesh->GetNSeg(); i++) + { + const Segment & seg = mesh -> LineSegment (i); + const Point3d p1 = mesh -> Point (seg.p1); + const Point3d p2 = mesh -> Point (seg.p2); + + 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); + } + + glPopAttrib (); + glDisable (GL_COLOR_MATERIAL); + } + + + if (vispar.drawedpoints) + { + glColor3d (0, 0, 1); + glPointSize( 3.0 ); + + glBegin( GL_POINTS ); + for (i = 1; i <= mesh -> GetNP(); i++) + { + const Point3d & p = mesh -> Point(i); + glVertex3f( p.X(), p.Y(), p.Z()); + } + glEnd(); + } + + 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 (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); + } + + glPopAttrib (); + glDisable (GL_COLOR_MATERIAL); + } + + + glPopMatrix(); + + if (vispar.drawcoordinatecross) + DrawCoordinateCross (); + DrawNetgenLogo (); + + glFinish(); +} + + +void VisualSceneSpecPoints :: BuildScene (int zoomall) +{ + int i, j, k; + + if (!mesh) + { + VisualScene::BuildScene(zoomall); + return; + } + + Box3d box; + + if (mesh->GetNSeg()) + { + box.SetPoint (mesh->Point (mesh->LineSegment(1).p1)); + for (i = 1; i <= mesh->GetNSeg(); i++) + { + box.AddPoint (mesh->Point (mesh->LineSegment(i).p1)); + box.AddPoint (mesh->Point (mesh->LineSegment(i).p2)); + } + } + else if (specpoints.Size() >= 2) + { + box.SetPoint (specpoints.Get(1).p); + for (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()) + center = mesh->Point (vispar.centerpoint); + else + center = Center (box.PMin(), box.PMax()); + + rad = 0.5 * Dist (box.PMin(), box.PMax()); + + + CalcTransformationMatrices(); +} + +} diff --git a/Netgen/libsrc/visualization/mvdraw.hpp b/Netgen/libsrc/visualization/mvdraw.hpp new file mode 100644 index 0000000000..691ac246cb --- /dev/null +++ b/Netgen/libsrc/visualization/mvdraw.hpp @@ -0,0 +1,352 @@ +#ifndef FILE_MVDRAW +#define FILE_MVDRAW + +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 drawededges; + int drawedpoints; + int drawedpointnrs; + int drawedtangents; + int drawededgenrs; + + int drawcurveproj; + int drawcurveprojedge; + + + int centerpoint; + int drawelement; + + // stl: + int stlshowtrias; + int stlshowfilledtrias; + int stlshowedges; + int stlshowmarktrias; + int stlshowactivechart; + int stlchartnumber; + int stlchartnumberoffset; + + bool whitebackground; + int stereo; + bool usedispllists; + bool drawcoordinatecross; + bool drawcolorbar; + bool drawnetgenlogo; + + +public: + VisualizationParameters(); +}; +extern VisualizationParameters vispar; + + + +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 Point3d center; + static double rad; + + static float lookatmat[16]; + static float transmat[16]; + static float rotmat[16]; + static float centermat[16]; + static float transformationmat[16]; + + GLdouble clipplane[4]; + + int changeval; + static double backcolor; + +public: + static GLuint fontbase; + static GLubyte * colortexture; + static GLuint coltexname; + static int ntexcols; + // static bool linear_colors; + int invcolor; + + +public: + VisualScene (); + virtual ~VisualScene(); + + virtual void BuildScene (int zoomall = 0); + virtual void DrawScene (); + + void CalcTransformationMatrices(); + void StandardRotation (const char * dir); + + void MouseMove(int oldx, int oldy, + int newx, int newy, + char mode); + + void LookAt (const Point<3> & cam, const Point<3> & obj, + const Point<3> & camup); + + void SetClippingPlane (); + + virtual void MouseDblClick (int px, int py); + + void SetLight (); + static void SetBackGroundColor (double col) + { backcolor = col; } + + void CreateTexture (int ncols, int linear); + void DrawColorBar (double minval, double maxval, int logscale = 0); + void DrawCoordinateCross (); + void DrawNetgenLogo (); + void SetOpenGlColor(double val, double valmin, double valmax, int logscale = 0); +}; + + +class VisualSceneGeometry : public VisualScene +{ + ARRAY<int> trilists; + int selsurf; +public: + VisualSceneGeometry (); + virtual ~VisualSceneGeometry (); + + virtual void SelectSurface (int aselsurf); + virtual void BuildScene (int zoomall = 0); + virtual void DrawScene (); +}; + + + +class VisualSceneSTLGeometry : public VisualScene +{ + ARRAY<int> trilists; + +public: + VisualSceneSTLGeometry (); + virtual ~VisualSceneSTLGeometry (); + + virtual void BuildScene (int zoomall = 0); + virtual void DrawScene (); +}; + + +class VisualSceneGeometry2d : public VisualScene +{ +public: + VisualSceneGeometry2d (); + virtual ~VisualSceneGeometry2d (); + + virtual void BuildScene (int zoomall = 0); + virtual void DrawScene (); +}; + + +#ifdef OCCGEOMETRY +class VisualSceneOCCGeometry : public VisualScene +{ + ARRAY<int> trilists; + ARRAY<int> linelists; + int selsurf; +public: + VisualSceneOCCGeometry (); + virtual ~VisualSceneOCCGeometry (); + + virtual void BuildScene (int zoomall = 0); + virtual void DrawScene (); +}; +#endif + + + + +#ifdef STEP +class VisualSceneSTEPGeometry : public VisualScene +{ + ARRAY<int> gllists; + +public: + VisualSceneSTEPGeometry (); + virtual ~VisualSceneSTEPGeometry (); + + virtual void BuildScene (int zoomall = 0); + virtual void DrawScene (); +}; +#endif + + +class VisualSceneSTLMeshing : public VisualScene +{ + ARRAY<int> trilists; + int selecttrig, nodeofseltrig; + +public: + VisualSceneSTLMeshing (); + virtual ~VisualSceneSTLMeshing (); + + virtual void BuildScene (int zoomall = 0); + virtual void DrawScene (); + virtual void MouseDblClick (int px, int py); + + int seltria; +}; + + + + +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 pointnumberlist; + + int tetlist; + int prismlist; + int pyramidlist; + int hexlist; + + int badellist; + int identifiedlist; + int domainsurflist; + + int vstimestamp, selecttimestamp; + int filledtimestamp; + int linetimestamp; + int pointnumbertimestamp; + + int tettimestamp; + int prismtimestamp; + int pyramidtimestamp; + int hextimestamp; + + int badeltimestamp; + int identifiedtimestamp; + int domainsurftimestamp; + + 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; } +private: + void BuildFilledList(); + void BuildLineList(); + 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); + + + +#endif + diff --git a/Netgen/libsrc/visualization/soldata.hpp b/Netgen/libsrc/visualization/soldata.hpp new file mode 100644 index 0000000000..b2c11cfbd0 --- /dev/null +++ b/Netgen/libsrc/visualization/soldata.hpp @@ -0,0 +1,41 @@ +#ifndef FILE_SOLDATA +#define FILE_SOLDATA + + + +class SolutionData +{ +protected: + std::string name; + int components; + bool iscomplex; + + // int dist; + // int order; +public: + SolutionData (const std::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 0; } + + virtual bool GetSurfValue (int selnr, + double lam1, double lam2, + double * values) + { return 0; } + +}; + + +#endif + diff --git a/Netgen/libsrc/visualization/stlmeshing.cpp b/Netgen/libsrc/visualization/stlmeshing.cpp new file mode 100644 index 0000000000..3fdbbadaf7 --- /dev/null +++ b/Netgen/libsrc/visualization/stlmeshing.cpp @@ -0,0 +1,1080 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <stlgeom.hpp> + +#include <meshing.hpp> +#include <visual.hpp> + +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, hmax; + + 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.9, 0.0, 0.0, 1 }; + float mat_colgreen[] = { 0.0, 0.9, 0.0, 1 }; + float mat_colblue[] = { 0.1, 0.1, 1., 1 }; + + float mat_colbluegreen[] = { 0.1, 0.5, 0.9, 1 }; + float mat_colpink[] = { 1., 0.1, 0.5, 1 }; + float mat_colviolet[] = { 1., 0.1, 1., 1 }; + float mat_colbrown[] = { 0.8, 0.6, 0.1, 1 }; + float mat_colorange[] = { 0.9, 0.7, 0.1, 1 }; + float mat_colturquis[] = { 0.0, 1., 0.8, 1 }; + + float mat_colgrey[] = { 0.3, 0.3, 0.3, 1 }; + + float mat_collred[] = { 1., 0.5, 0.5, 1 }; + float mat_collgreen[] = { 0.2, 1., 0.2, 1 }; + float mat_collbrown[] = { 1., 0.8, 0.3, 1 }; + + float mat_collgrey[] = { 0.8, 0.8, 0.8, 1 }; + float mat_colmgrey[] = { 0.4, 0.4, 0.4, 1 }; + + float mat_colstlbody[] = { 0., 0., 0.8, 1 }; + float mat_colseltrig[] = { 0.7, 0.7, 0.3, 1 }; + float mat_colseledge[] = { 0.7, 0.7, 1., 1 }; + + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colblue); + + float pgoff = 0.5; + + 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.2, 0.2, 0.2, 1 }; + 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) +{ + int i, j, k; + + 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/Netgen/libsrc/visualization/visual.hpp b/Netgen/libsrc/visualization/visual.hpp new file mode 100644 index 0000000000..3e5910b351 --- /dev/null +++ b/Netgen/libsrc/visualization/visual.hpp @@ -0,0 +1,26 @@ +#ifndef FILE_VISUAL +#define FILE_VISUAL + +/* *************************************************************************/ +/* File: visual.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 02. Dec. 01 */ +/* *************************************************************************/ + +/* + +Visualization + +*/ + +#include <incvis.hpp> + +namespace netgen +{ +#include "mvdraw.hpp" +#include "soldata.hpp" +#include "vssolution.hpp" +#include "meshdoc.hpp" +} + +#endif diff --git a/Netgen/libsrc/visualization/vscsg.cpp b/Netgen/libsrc/visualization/vscsg.cpp new file mode 100644 index 0000000000..42891f0a63 --- /dev/null +++ b/Netgen/libsrc/visualization/vscsg.cpp @@ -0,0 +1,199 @@ +#include <mystdlib.h> +#include "incvis.hpp" + +#include <myadt.hpp> +#include <meshing.hpp> +#include <csg.hpp> +#include <stlgeom.hpp> + + +namespace netgen +{ +#include "mvdraw.hpp" + +/* *********************** Draw Geometry **************** */ + + + + +extern 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); + + glPopMatrix(); + + glDisable(GL_CLIP_PLANE0); + + DrawCoordinateCross (); + DrawNetgenLogo (); + + glFinish(); + +} + + +void VisualSceneGeometry :: BuildScene (int zoomall) +{ + int i, j, k; + + Box<3> box; + int hasp = 0; + for (i = 0; i < geometry->GetNTopLevelObjects(); i++) + { + const TriangleApproximation & ta = + *geometry->GetTriApprox(i); + if (!&ta) continue; + + for (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 (i = 0; i < trilists.Size(); i++) + glDeleteLists (trilists[i], 1); + trilists.SetSize(0); + + for (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 (j = 0; j < ta.GetNT(); j++) + { + + for (k = 0; k < 3; k++) + { + int pi = ta.GetTriangle(j)[k]; + glNormal3f (ta.GetNormal (pi)(0), + ta.GetNormal (pi)(1), + ta.GetNormal (pi)(2)); + glVertex3f (ta.GetPoint(pi)(0), + ta.GetPoint(pi)(1), + ta.GetPoint(pi)(2)); + } + } + glEnd (); + } + glEndList (); + } + +} + + + + + +} diff --git a/Netgen/libsrc/visualization/vsmesh.cpp b/Netgen/libsrc/visualization/vsmesh.cpp new file mode 100644 index 0000000000..f88cb55284 --- /dev/null +++ b/Netgen/libsrc/visualization/vsmesh.cpp @@ -0,0 +1,2741 @@ +#include <mystdlib.h> +#include "incvis.hpp" + + +#include <myadt.hpp> +#include <meshing.hpp> +#include <csg.hpp> +#include <stlgeom.hpp> + +namespace netgen +{ + +#include "mvdraw.hpp" + + + // #define FAST3DELEMENTS + + + + extern AutoPtr<Mesh> mesh; + extern STLGeometry * stlgeometry; + VisualSceneMesh vsmesh; + + + + VisualSceneMesh :: VisualSceneMesh () + : VisualScene() + { + filledlist = 0; + linelist = 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(); + 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; + } + + VisualSceneMesh :: ~VisualSceneMesh () + { + ; + } + + + + + ARRAY<Point3d> drawel; + void VisualSceneMesh :: DrawScene () + { + /* + if (multithread.running) + { + VisualScene::DrawScene(); + return; + } + */ + int i; + + + if (!mesh) + { + VisualScene::DrawScene(); + return; + } + + + lock = NULL; + + 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); + + + 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,1); + glEnable (GL_POLYGON_OFFSET_FILL); + + SetClippingPlane (); + + if (vispar.drawfilledtrigs) + { + BuildFilledList (); + glCallList (filledlist); + } + + if (vispar.drawbadels) + glCallList (badellist); + + if (vispar.drawprisms) + { + BuildPrismList (); + static float prismcol[] = { 1.0f, 1.0f, 0.0f, 1.0f }; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, prismcol); + glLineWidth (1.0f); + glCallList (prismlist); + } + + if (vispar.drawpyramids) + { + BuildPyramidList (); + static float pyramidcol[] = { 1.0f, 1.0f, 0.0f, 1.0f }; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, pyramidcol); + glLineWidth (1.0f); + glCallList (pyramidlist); + } + + if (vispar.drawhexes) + { + BuildHexList (); + static float hexcol[] = { 1.0f, 0.0f, 0.0f, 1.0f }; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, hexcol); + glLineWidth (1.0f); + glCallList (hexlist); + } + + + + if (vispar.drawtets) + { + BuildTetList (); + static float tetcol[] = { 1.0f, 1.0f, 0.0f, 1.0f }; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tetcol); + glLineWidth (1.0f); + 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); + + BuildLineList (); + glCallList (linelist); + + glDisable (GL_POLYGON_OFFSET_LINE); + } + + /* + // not drawing subdivision mesh + + if (vispar.drawtets) + { + glCallList (tetlist); + } + + if (vispar.drawprisms) + { + glCallList (prismlist); + } + + if (vispar.drawpyramids) + { + glCallList (pyramidlist); + } + + */ + + 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) + { + GLfloat matcoledge[] = { 0, 0, 1, 1 }; + GLfloat matcolsingedge[] = { 1, 0, 1, 1 }; + + glEnable (GL_POLYGON_OFFSET_LINE); + glPolygonOffset (-1, -1); + glLineWidth (2); + + + for (i = 1; i <= mesh->GetNSeg(); i++) + { + const Segment & seg = mesh->LineSegment(i); + const Point3d & p1 = (*mesh)[seg.p1]; + const Point3d & p2 = (*mesh)[seg.p2]; + + if (seg.singedge) + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, + matcolsingedge); + else + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, + matcoledge); + + if (seg.edgenr == seledge) + glLineWidth(5); + else + glLineWidth(2); + + if (mesh->GetCurvedElements().IsHighOrder()) { + + int j; + int hoplotn = 1 << vispar.subdivisions; + // mesh->GetCurvedElements().GetNVisualSubsecs(); + + Point<3> x; + glBegin (GL_LINE_STRIP); + + for (j = 0; j <= hoplotn; j++) { + mesh->GetCurvedElements().CalcSegmentTransformation ((double) j/hoplotn, i-1, x); + glVertex3d (x(0), x(1), x(2)); + } + + glEnd(); + + } else { + + glBegin (GL_LINES); + glVertex3f (p1.X(), p1.Y(), p1.Z()); + glVertex3f (p2.X(), p2.Y(), p2.Z()); + glEnd(); + + } + } + + glLineWidth (2); + glDisable (GL_POLYGON_OFFSET_LINE); + } + + + if (selpoint > 0 && selpoint <= mesh->GetNP()) + { + 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(); + + if (vispar.colormeshsize) + DrawColorBar (minh, maxh, 1); + + DrawCoordinateCross (); + DrawNetgenLogo (); + + if (lock) + { + lock -> UnLock(); + delete lock; + } + + glFinish(); + } + + + void VisualSceneMesh :: BuildScene (int zoomall) + { + if (!mesh) + { + VisualScene::BuildScene (zoomall); + return; + } + + int i, j; + + + Point3d pmin, pmax; + static double oldrad = 0; + + ARRAY<Element2d> faces; + + if (mesh->GetTimeStamp() > vstimestamp || zoomall) + { + mesh->GetBox (pmin, pmax, SURFACEPOINT); + + 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 > 1.5 * oldrad || + mesh->GetMajorTimeStamp() > vstimestamp || + zoomall) + { + CalcTransformationMatrices(); + oldrad = rad; + } + vstimestamp = mesh->GetTimeStamp(); + } + + 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 (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); + } + + if (vispar.drawedgenumbers) + { + const MeshTopology & top = mesh->GetTopology(); + for (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); + } + } + + + if (vispar.drawfacenumbers) + { + const MeshTopology & top = mesh->GetTopology(); + ARRAY<int> v; + for (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); + } + } + + + 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 (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 (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 (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 (i = 1; i <= mesh->GetNE(); i++) + { + Element el = mesh->VolumeElement (i); + int hascp = 0; + for (j = 1; j <= el.GetNP(); j++) + if (el.PNum(j) == vispar.centerpoint) + hascp = 1; + + if (hascp) + { + (*testout) << "draw el " << i << " : "; + for (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 (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 (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 (i = 1; i <= mesh->GetNSE(); i++) + { + Element2d el = mesh->SurfaceElement(i); + if (!el.BadElement()) + continue; + + int drawel = 1; + for (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 (j = 0; j < 6; j++) + { + glVertex3dv (&mesh->Point (el.PNum(lines[j][0])).X()); + glVertex3dv (&mesh->Point (el.PNum(lines[j][0])).X()); + } + glEnd(); + break; + } + + case QUAD6: + { + int lines[6][2] = { + { 1, 5 }, { 2, 5 }, + { 3, 6 }, { 4, 6 }, + { 1, 4 }, { 2, 3 } }; + + glBegin (GL_LINES); + + for (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++) + INDEX_2_HASHTABLE<int> & idpts = + mesh->GetIdentifications().GetIdentifiedPoints(); + if (&idpts) + for (i = 1; i <= idpts.GetNBags(); i++) + for (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 (); + } + } + + + + + void VisualSceneMesh :: BuildFilledList() + { + clock_t starttime, endtime; + starttime = clock(); + + int i, j; + SurfaceElementIndex sei; + + if (filledtimestamp > mesh->GetTimeStamp () && + filledtimestamp > selecttimestamp) + return; + + if (!lock) + { + lock = new NgLock (mesh->Mutex()); + lock -> Lock(); + } + + filledtimestamp = NextTimeStamp(); + + if (filledlist) + glDeleteLists (filledlist, 1); + + + int checkvicinity = (stlgeometry != NULL) && stldoctor.showvicinity; + + filledlist = glGenLists (1); + glNewList (filledlist, GL_COMPILE); + + + glEnable (GL_NORMALIZE); + + glLineWidth (1.0f); + + Vector locms; + + if (vispar.colormeshsize) + { + glEnable (GL_COLOR_MATERIAL); + locms.SetSize (mesh->GetNP()); + double maxh = -1; + double minh = 1e99; + for (i = 1; i <= locms.Size(); i++) + { + Point3d p = mesh->Point(i); + locms.Elem(i) = mesh->GetH (p); + if (locms.Elem(i) > maxh) maxh = locms.Elem(i); + if (locms.Elem(i) < minh) minh = locms.Elem(i); + } + // minh = locms.Min(); + // maxh = locms.Max(); + if (!locms.Size()) + { minh = 1; maxh = 10; } + } + else + glDisable (GL_COLOR_MATERIAL); + + + GLfloat matcol[] = { 0, 1, 0, 1 }; + GLfloat matcolsel[] = { 1, 0, 0, 1 }; + + for (int col = 1; col <= 2; col++) + { + if (col == 2) + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matcolsel); + else + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matcol); + + + for (sei = 0; sei < mesh->GetNSE(); sei++) + { + const Element2d & el = (*mesh)[sei]; + + bool drawel = !el.IsDeleted(); + + for (j = 0; j < el.GetNP(); j++) + { + if (checkvicinity && !stlgeometry->Vicinity(el.GeomInfoPi(j+1).trignum)) + drawel = 0; + } + + if (!drawel) + continue; + + if (vispar.colormeshsize && col == 2) + continue; + if (!vispar.colormeshsize && + (col == 2) != (el.GetIndex() == selface)) + continue; + + glLoadName (sei+1); + + switch (el.GetType()) + { + case TRIG: + { + CurvedElements & curv = mesh->GetCurvedElements(); + if (curv.IsHighOrder() && curv.IsSurfaceElementCurved(sei)) + { + int hoplotn = 1 << vispar.subdivisions; + // int hoplotn = curv.GetNVisualSubsecs(); + + Point<2> xr[3]; + Point<3> xg; + Vec<3> dx, dy, n; + + glBegin (GL_TRIANGLES); + + for (int i = 0; i < hoplotn; i++) + for (int j = 0; j < hoplotn-i; j++) + for (int k = 0; k < 2; k++) + { + if (k == 0) + { + 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/hoplotn; xr[2](1) = (double)(j+1)/hoplotn; + } else + { + if (j == hoplotn-i-1) continue; + xr[0](0) = (double)(i+1)/hoplotn; xr[0](1) = (double) j/hoplotn; + xr[1](0) = (double)(i+1)/hoplotn; xr[1](1) = (double)(j+1)/hoplotn; + xr[2](0) = (double) i/hoplotn; xr[2](1) = (double)(j+1)/hoplotn; + }; + + for (int l=0; l<3; 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_TRIANGLES); + + Point<3> lp0 = (*mesh) [el.PNum(1)]; + Point<3> lp1 = (*mesh) [el.PNum(2)]; + Point<3> lp2 = (*mesh) [el.PNum(3)]; + + Vec<3> n = Cross (lp1-lp0, lp2-lp0); + n.Normalize(); + + glNormal3d (n(0), n(1), n(2)); + + + if (vispar.colormeshsize) + SetOpenGlColor (locms.Get(el.PNum(1)), minh, maxh, 1); + glVertex3d (lp0(0), lp0(1), lp0(2)); + if (vispar.colormeshsize) + SetOpenGlColor (locms.Get(el.PNum(2)), minh, maxh, 1); + glVertex3d (lp1(0), lp1(1), lp1(2)); + if (vispar.colormeshsize) + SetOpenGlColor (locms.Get(el.PNum(3)), minh, maxh, 1); + glVertex3d (lp2(0), lp2(1), lp2(2)); + + glEnd(); + } + + break; + + } + case QUAD: + { + // cout << "BuildFilledList: QUAD" << endl; + CurvedElements & curv = mesh->GetCurvedElements(); + if (curv.IsHighOrder() && curv.IsSurfaceElementCurved(sei)) + { + int hoplotn = 1 << vispar.subdivisions; + // int hoplotn = curv.GetNVisualSubsecs(); + + 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 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: + { + 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++) + { + Point3d & lp1 = mesh->Point (el.PNum(trigs[j][0])); + Point3d & lp2 = mesh->Point (el.PNum(trigs[j][1])); + Point3d & lp3 = mesh->Point (el.PNum(trigs[j][2])); + 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 QUAD6: + { + glBegin (GL_QUADS); + static int quads[2][4] = { + { 1, 5, 6, 4 }, + { 5, 2, 3, 6 } }; + + for (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; + } + default: + PrintSysError ("Cannot draw (2) surface element of type ", + int(el.GetType())); + } + } + } + glLoadName (0); + glEndList (); + + endtime = clock(); + + // cout << "BuildFillList time = " << double(endtime - starttime)/CLOCKS_PER_SEC << endl; + } + + + void VisualSceneMesh :: BuildLineList() + { + int j; + SurfaceElementIndex sei; + + if (linetimestamp > mesh->GetTimeStamp () && + linetimestamp > selecttimestamp) + return; + + if (!lock) + { + lock = new NgLock (mesh->Mutex()); + lock -> Lock(); + } + + linetimestamp = NextTimeStamp(); + + + int checkvicinity = (stlgeometry != NULL) && stldoctor.showvicinity; + + if (linelist) + glDeleteLists (linelist, 1); + + + linelist = glGenLists (1); + glNewList (linelist, GL_COMPILE); + + + glLineWidth (1.0f); + + for (sei = 0; sei < mesh->GetNSE(); sei++) + { + const Element2d & el = (*mesh)[sei]; + + bool drawel = !el.IsDeleted(); + for (j = 0; j < el.GetNP(); j++) + { + if (checkvicinity && !stlgeometry->Vicinity(el.GeomInfoPi(j+1).trignum)) + drawel = 0; + } + + if (!drawel) + continue; + + switch (el.GetType()) + { + /* + case TRIG: + { + CurvedElements & curv = mesh->GetCurvedElements(); + if (curv.IsHighOrder() && curv.IsSurfaceElementCurved(sei)) + { + const MeshTopology & top = mesh->GetTopology(); + + int hoplotn = 1 << vispar.subdivisions; + // int hoplotn = curv.GetNVisualSubsecs(); + + Point<2> xr[3]; + Point<3> xg; + Vec<3> dx, dy, n; + + glBegin (GL_TRIANGLES); + + for (int i = 0; i < hoplotn; i++) + for (int j = 0; j < hoplotn-i; j++) + for (int k = 0; k < 2; k++) + { + if (k == 0) + { + 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/hoplotn; xr[2](1) = (double)(j+1)/hoplotn; + } else + { + if (j == hoplotn-i-1) continue; + xr[0](0) = (double)(i+1)/hoplotn; xr[0](1) = (double) j/hoplotn; + xr[1](0) = (double)(i+1)/hoplotn; xr[1](1) = (double)(j+1)/hoplotn; + xr[2](0) = (double) i/hoplotn; xr[2](1) = (double)(j+1)/hoplotn; + }; + + for (int l=0; l<3; 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_TRIANGLES); + + Point<3> lp0 = mesh->Point (el.PNum(1)); + Point<3> lp1 = mesh->Point (el.PNum(2)); + Point<3> lp2 = mesh->Point (el.PNum(3)); + + Vec<3> n = Cross (lp1-lp0, lp2-lp0); + n.Normalize(); + + glNormal3d (n(0), n(1), n(2)); + glVertex3d (lp0(0), lp0(1), lp0(2)); + glVertex3d (lp1(0), lp1(1), lp1(2)); + glVertex3d (lp2(0), lp2(1), lp2(2)); + + glEnd(); + } + + break; + + } + + case QUAD: + { + // cout << "BuildFilledList: QUAD" << endl; + CurvedElements & curv = mesh->GetCurvedElements(); + if (curv.IsHighOrder() && curv.IsSurfaceElementCurved(sei)) + { + const MeshTopology & top = mesh->GetTopology(); + + int hoplotn = 1 << vispar.subdivisions; + // int hoplotn = curv.GetNVisualSubsecs(); + + 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 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 TRIG: + { + CurvedElements & curv = mesh->GetCurvedElements(); + if (curv.IsHighOrder() && curv.IsSurfaceElementCurved(sei)) + { + Point<2> xr; + Point<3> xg; + Vec<3> n; + + int hoplotn = 1 << vispar.subdivisions; + // int hoplotn = curv.GetNVisualSubsecs(); + + glBegin (GL_LINE_STRIP); + + for (int side = 0; side < 3; 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) = (double) (hoplotn-i)/hoplotn; + xr(1) = (double) i/hoplotn; + break; + case 2: + xr(0) = 0.; + xr(1) = (double) (hoplotn-i)/hoplotn; + break; + } + + Mat<3,2> dxdxi; + + curv.CalcSurfaceTransformation (xr, sei, xg, dxdxi); + glVertex3d (xg(0), xg(1), xg(2)); + + } + + } + glEnd(); + + } else { + + glBegin (GL_TRIANGLES); + + Point<3> lp0 = (*mesh) [el.PNum(1)]; + Point<3> lp1 = (*mesh) [el.PNum(2)]; + Point<3> lp2 = (*mesh) [el.PNum(3)]; + + glVertex3dv (lp0); + glVertex3d (lp1(0), lp1(1), lp1(2)); + glVertex3d (lp2(0), lp2(1), lp2(2)); + + glEnd(); + + } + + break; + + } + + case QUAD: + { + CurvedElements & curv = mesh->GetCurvedElements(); + if (curv.IsHighOrder() && curv.IsSurfaceElementCurved(sei)) + { + Point<2> xr; + Point<3> xg; + + int hoplotn = 1 << vispar.subdivisions; + // int hoplotn = curv.GetNVisualSubsecs(); + + 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; + } + + Mat<3,2> dxdxi; + + curv.CalcSurfaceTransformation (xr, sei, xg, dxdxi); + 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))); + 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 (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 (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 (4) surface element of type ", + int(el.GetType())); + } + } + + glEndList (); + } + + void VisualSceneMesh :: BuildPointNumberList() + { + ; + } + + void VisualSceneMesh :: BuildTetList() + { + + +#ifdef FAST3DELEMENTS + + + cout << "start fast test" << endl; + + int i, j; + ARRAY<Element2d> faces; + + 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); + + + BitArray shownode(mesh->GetNP()); + if (vispar.clipenable) + { + shownode.Clear(); + for (i = 1; i <= shownode.Size(); i++) + { + Point3d p = mesh->Point(i); + + double val = + p.X() * clipplane[0] + + p.Y() * clipplane[1] + + p.Z() * 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 } + }; + + + ARRAY<int> elfaces; + + const MeshTopology & top = mesh->GetTopology(); + CurvedElements & curv = mesh->GetCurvedElements(); + + ARRAY<int> displayface(top.GetNFaces()); + for (i = 0; i < top.GetNFaces(); i++) + displayface[i] = -1; + + + for (i = 1; i <= mesh->GetNE(); i++) + { + if (vispar.drawtetsdomain > 0 && + vispar.drawtetsdomain != mesh->VolumeElement(i).GetIndex()) + continue; + + Element el = (*mesh)[(ElementIndex) (i-1)]; + + if (el.GetType() == TET) + { + if (el.PNum(1)) + { + bool drawtet = 1; + for (j = 1; j <= el.GetNP(); j++) + if (!shownode.Test(el.PNum(j))) + drawtet = 0; + if (!drawtet) continue; + + { + top.GetElementFaces (i, elfaces); + + for (j = 0; j < 4; j++) + displayface[elfaces[j]-1] *= -1; + } + } + } + } + + + for (i = 1; i <= mesh->GetNE(); i++) + { + if (vispar.drawtetsdomain > 0 && + vispar.drawtetsdomain != mesh->VolumeElement(i).GetIndex()) + continue; + + if (mesh->VolumeElement(i).GetType() == TET) + { + // copy to be thread-safe + Element el = mesh->VolumeElement (i); + el.GetSurfaceTriangles (faces); + + if (el.PNum(1)) + { + bool drawtet = 1; + for (j = 1; j <= el.GetNP(); j++) + if (!shownode.Test(el.PNum(j))) + drawtet = 0; + if (!drawtet) continue; + + int ind = el.GetIndex() % 4; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tetcols[ind]); + + + top.GetElementFaces (i, elfaces); + + glBegin (GL_TRIANGLES); + + for (j = 0; j < faces.Size(); j++) + { + if (displayface[elfaces[j]-1] == -1) continue; + + Element2d & face = faces.Elem(j+1); + + if (curv.IsHighOrder() && curv.IsElementCurved(i-1)) + { + int hoplotn = 1 << vispar.subdivisions; + // int hoplotn = curv.GetNVisualSubsecs(); + + const Point3d * facepoint = MeshTopology :: GetVertices (TET); + const ELEMENT_FACE * elface = MeshTopology :: GetFaces(TET); + + Vec<3> x0,x1,d0,d1; + Point<3> xg; + x0 = facepoint[face.PNum(3)-1] - facepoint[face.PNum(1)-1]; + x1 = facepoint[face.PNum(2)-1] - facepoint[face.PNum(1)-1]; + x0.Normalize(); + x1.Normalize(); + + for (int m0 = 0; m0 < hoplotn; m0++) + for (int m1 = 0; m1 < hoplotn-m0; m1++) + for (int k = 0; k < 2; k++) + { + Vec<3> dx, dy, dz, n; + Point<4> la[3]; + int l; + for (l = 0; l<3; l++) la[l] = Point<4>(0.,0.,0.,0.); + + if (k == 0) + { + la[0](face.PNum(1)-1) = (m0 )/(double)hoplotn; + la[0](face.PNum(2)-1) = (m1 )/(double)hoplotn; + la[0](face.PNum(3)-1) = 1-la[0](face.PNum(1)-1)-la[0](face.PNum(2)-1); + + la[1](face.PNum(1)-1) = (m0+1)/(double)hoplotn; + la[1](face.PNum(2)-1) = (m1 )/(double)hoplotn; + la[1](face.PNum(3)-1) = 1-la[1](face.PNum(1)-1)-la[1](face.PNum(2)-1); + + la[2](face.PNum(1)-1) = (m0 )/(double)hoplotn; + la[2](face.PNum(2)-1) = (m1+1)/(double)hoplotn; + la[2](face.PNum(3)-1) = 1-la[2](face.PNum(1)-1)-la[2](face.PNum(2)-1); + } else + { + if (m1 == hoplotn-m0-1) continue; + la[0](face.PNum(1)-1) = (m0+1)/(double)hoplotn; + la[0](face.PNum(2)-1) = (m1+1)/(double)hoplotn; + la[0](face.PNum(3)-1) = 1-la[0](face.PNum(1)-1)-la[0](face.PNum(2)-1); + + la[1](face.PNum(1)-1) = (m0 )/(double)hoplotn; + la[1](face.PNum(2)-1) = (m1+1)/(double)hoplotn; + la[1](face.PNum(3)-1) = 1-la[1](face.PNum(1)-1)-la[1](face.PNum(2)-1); + + la[2](face.PNum(1)-1) = (m0+1)/(double)hoplotn; + la[2](face.PNum(2)-1) = (m1 )/(double)hoplotn; + la[2](face.PNum(3)-1) = 1-la[2](face.PNum(1)-1)-la[2](face.PNum(2)-1); + } + + for (l = 0; l<3; l++) + { + Mat<3,3> dxdxi; + Point<3> xr( la[l](0), la[l](1), la[l](2) ); + curv.CalcElementTransformation (xr, 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); + } + + d0 = x0(0)*dx + x0(1)*dy + x0(2)*dz; + d1 = x1(0)*dx + x1(1)*dy + x1(2)*dz; + n = Cross (d0, d1); + glNormal3d ( n(0), n(1), n(2)); + glVertex3d (xg(0), xg(1), xg(2)); + } + } + + } else { + 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, lp3), Vec3d (lp1, lp2)); + 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(); + } + + } + } + glEndList (); + + + + +#else + + + int i, j, k, l; + ARRAY<Element2d> faces; + + 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); + + + BitArray shownode(mesh->GetNP()); + if (vispar.clipenable) + { + shownode.Clear(); + for (i = 1; i <= shownode.Size(); i++) + { + Point3d p = mesh->Point(i); + + double val = + p.X() * clipplane[0] + + p.Y() * clipplane[1] + + p.Z() * 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 } + }; + + + // ARRAY<int> elfaces; + + // const MeshTopology & top = mesh->GetTopology(); + CurvedElements & curv = mesh->GetCurvedElements(); + + + for (i = 1; i <= mesh->GetNE(); i++) + { + if (vispar.drawtetsdomain > 0 && + vispar.drawtetsdomain != mesh->VolumeElement(i).GetIndex()) + continue; + + if (mesh->VolumeElement(i).GetType() == TET) + { + // copy to be thread-safe + Element el = mesh->VolumeElement (i); + el.GetSurfaceTriangles (faces); + + if (el.PNum(1)) + { + int drawtet = 1; + for (j = 1; j <= el.GetNP(); j++) + if (!shownode.Test(el.PNum(j))) + drawtet = 0; + if (!drawtet) continue; + + Point3d c; + if (vispar.shrink < 1) + c = Center (Center (mesh->Point (el.PNum(1)), + mesh->Point (el.PNum(2))), + Center (mesh->Point (el.PNum(3)), + mesh->Point (el.PNum(4)))); + + + + int ind = el.GetIndex() % 4; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tetcols[ind]); + + + // top.GetElementFaces (i, elfaces); + + glBegin (GL_TRIANGLES); + + for (j = 0; j < faces.Size(); j++) + { + Element2d & face = faces.Elem(j+1); + + if (curv.IsHighOrder() && curv.IsElementCurved(i-1)) + { + int hoplotn = 1 << vispar.subdivisions; + // int hoplotn = curv.GetNVisualSubsecs(); + + const Point3d * facepoint = MeshTopology :: GetVertices (TET); + const ELEMENT_FACE * elface = MeshTopology :: GetFaces(TET); + + Vec<3> x0,x1,d0,d1; + Point<3> xg; + x0 = facepoint[face.PNum(3)-1] - facepoint[face.PNum(1)-1]; + x1 = facepoint[face.PNum(2)-1] - facepoint[face.PNum(1)-1]; + x0.Normalize(); + x1.Normalize(); + + for (int m0 = 0; m0 < hoplotn; m0++) + for (int m1 = 0; m1 < hoplotn-m0; m1++) + for (k = 0; k < 2; k++) + { + Vec<3> dx, dy, dz, n; + Point<4> la[3]; + + for (l = 0; l<3; l++) la[l] = Point<4>(0.,0.,0.,0.); + + if (k == 0) + { + la[0](face.PNum(1)-1) = (m0 )/(double)hoplotn; + la[0](face.PNum(2)-1) = (m1 )/(double)hoplotn; + la[0](face.PNum(3)-1) = 1-la[0](face.PNum(1)-1)-la[0](face.PNum(2)-1); + + la[1](face.PNum(1)-1) = (m0+1)/(double)hoplotn; + la[1](face.PNum(2)-1) = (m1 )/(double)hoplotn; + la[1](face.PNum(3)-1) = 1-la[1](face.PNum(1)-1)-la[1](face.PNum(2)-1); + + la[2](face.PNum(1)-1) = (m0 )/(double)hoplotn; + la[2](face.PNum(2)-1) = (m1+1)/(double)hoplotn; + la[2](face.PNum(3)-1) = 1-la[2](face.PNum(1)-1)-la[2](face.PNum(2)-1); + } else + { + if (m1 == hoplotn-m0-1) continue; + la[0](face.PNum(1)-1) = (m0+1)/(double)hoplotn; + la[0](face.PNum(2)-1) = (m1+1)/(double)hoplotn; + la[0](face.PNum(3)-1) = 1-la[0](face.PNum(1)-1)-la[0](face.PNum(2)-1); + + la[1](face.PNum(1)-1) = (m0 )/(double)hoplotn; + la[1](face.PNum(2)-1) = (m1+1)/(double)hoplotn; + la[1](face.PNum(3)-1) = 1-la[1](face.PNum(1)-1)-la[1](face.PNum(2)-1); + + la[2](face.PNum(1)-1) = (m0+1)/(double)hoplotn; + la[2](face.PNum(2)-1) = (m1 )/(double)hoplotn; + la[2](face.PNum(3)-1) = 1-la[2](face.PNum(1)-1)-la[2](face.PNum(2)-1); + } + + for (l = 0; l<3; l++) + { + Mat<3,3> dxdxi; + Point<3> xr( la[l](0), la[l](1), la[l](2) ); + curv.CalcElementTransformation (xr, 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); + } + + d0 = x0(0)*dx + x0(1)*dy + x0(2)*dz; + d1 = x1(0)*dx + x1(1)*dy + x1(2)*dz; + n = Cross (d0, d1); + glNormal3d ( n(0), n(1), n(2)); + glVertex3d (xg(0), xg(1), xg(2)); + } + } + + } else { + 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 (); + + + +#endif +} + + +void VisualSceneMesh :: BuildPrismList() +{ + int i, j; + + prismlist = glGenLists (1); + glNewList (prismlist, GL_COMPILE); + + static float prismcol[] = { 0.0f, 1.0f, 1.0f, 1.0f }; + glLineWidth (1.0f); + + ARRAY<Element2d> faces; + + for (i = 1; i <= mesh->GetNE(); i++) + { + if (mesh->VolumeElement(i).GetType() == PRISM) + { + // copy to be thread-safe + Element el = mesh->VolumeElement (i); + el.GetSurfaceTriangles (faces); + + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, prismcol); + if (el.PNum(1)) + { + CurvedElements & curv = mesh->GetCurvedElements(); + if (curv.IsHighOrder() && curv.IsElementCurved(i-1)) + { + 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; + } + } + + 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() +{ + int i, j; + + 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; + + for (i = 1; i <= mesh->GetNE(); i++) + { + Element el = mesh->VolumeElement (i); + + if (el.GetType() == HEX && + el.PNum(1)) + { + el.GetSurfaceTriangles (faces); + + CurvedElements & curv = mesh->GetCurvedElements(); + if (curv.IsHighOrder() && curv.IsElementCurved(i-1)) + { + cerr << "draw curved hex not implemented" << endl; + 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 <= 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); + + 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 :: BuildPyramidList() +{ + int i, j; + + pyramidlist = glGenLists (1); + glNewList (pyramidlist, GL_COMPILE); + + static float pyramidcol[] = { 1.0f, 0.0f, 1.0f, 1.0f }; + glLineWidth (1.0f); + ARRAY<Element2d> faces; + + for (i = 1; i <= mesh->GetNE(); i++) + { + if (mesh->VolumeElement(i).GetType() == PYRAMID) + { + // copy to be thread-safe + Element el = mesh->VolumeElement (i); + + Point3d c(0,0,0); + if (vispar.shrink < 1) + { + for (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); + + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, pyramidcol); + if (el.PNum(1)) + { + 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, 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) +{ + 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]; + /* + 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.p1 == selpoint && seg.p2 == selpoint2 || + seg.p2 == selpoint && seg.p1 == selpoint2) + { + seledge = seg.edgenr; + cout << "seledge = " << seledge << endl; + } + } + + } + else + { + selface = -1; + selelement = -1; + selpoint = -1; + selpoint2 = -1; + } + + glDisable(GL_CLIP_PLANE0); + + selecttimestamp = NextTimeStamp(); +} + + + + + +} + + + + + + + + + + diff --git a/Netgen/libsrc/visualization/vssolution.cpp b/Netgen/libsrc/visualization/vssolution.cpp new file mode 100644 index 0000000000..8678fc900d --- /dev/null +++ b/Netgen/libsrc/visualization/vssolution.cpp @@ -0,0 +1,2738 @@ +#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; + + + VisualSceneSolution :: VisualSceneSolution () + : VisualScene() + { + surfellist = 0; + linelist = 0; + clipplanelist = 0; + isolinelist = 0; + surface_vector_list = 0; + cone_list = 0; + + surfeltimestamp = GetTimeStamp(); + clipplanetimestamp = GetTimeStamp(); + solutiontimestamp = GetTimeStamp(); + fieldlinestimestamp = GetTimeStamp(); + surface_vector_timestamp = GetTimeStamp(); + AddVisualizationScene ("solution", &vssolution); + } + + VisualSceneSolution :: ~VisualSceneSolution () + { + ; + } + + void VisualSceneSolution :: AddSolutionData (SolData * sd) + { + int i, funcnr = -1; + + for (i = 0; i < soldata.Size(); i++) + { + if (strcmp (soldata[i]->name, sd->name) == 0) + { + 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; + } + } + solutiontimestamp = NextTimeStamp(); + } + + /* + (*testout) << "set sol-data " << nsd->name + << ", size = " << nsd->size << endl; + if (nsd->data) + for (i = 0; i < nsd->size; i++) + (*testout) << i << ": " << nsd->data[i] << endl; + */ + } + + void VisualSceneSolution :: ClearSolutionData () + { + 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); + int i, j, k; + + ofstream ost(filename); + for (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; + } + + ost << endl; + for (j = 0; j < sol.size; j++) + { + for (k = 0; k < sol.components; k++) + ost << sol.data[j*sol.dist+k] << " "; + ost << "\n"; + } + } + } + + + + + void VisualSceneSolution :: DrawScene () + { + /* + if (multithread.running) + { + VisualScene::DrawScene(); + return; + } + */ + int i, j, k; + + if (!mesh) + { + VisualScene::DrawScene(); + return; + } + + static NgLock mem_lock(mem_mutex); + mem_lock.Lock(); + + /* + lock = NULL; + if (!lock) + { + lock = new NgLock (mesh->Mutex()); + lock -> Lock(); + } + */ + + BuildScene(); + + // either continuous, or discrete coloring + CreateTexture (numtexturecols, lineartexture); + + glClearColor(backcolor, backcolor, backcolor, 1.0); + 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) + glEnable (GL_TEXTURE_1D); + + + if (vispar.drawfilledtrigs) + { + SetClippingPlane (); + + glCallList (surfellist); + glCallList (surface_vector_list); + + glDisable(GL_CLIP_PLANE0); + } + + if (showclipsolution) + glCallList (clipplanelist); + + + if (draw_fieldlines) + { + BuildFieldLinesPlot (); + + if (num_fieldlineslists <= 1) + glCallList (fieldlineslist); + else + { + int start = int (time / 10 * num_fieldlineslists); + for (int ln = 0; ln < 10; ln++) + { + int nr = fieldlineslist + (start + ln) % num_fieldlineslists; + glCallList (nr); + } + } + } + + if (usetexture) + glDisable (GL_TEXTURE_1D); + + + + glDisable (GL_POLYGON_OFFSET_FILL); + + glDisable (GL_COLOR_MATERIAL); + + + 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 (); + + if (numisolines) + { + glCallList (isolinelist); + } + else + { + glCallList (linelist); + } + + glDisable(GL_CLIP_PLANE0); + } + + + + glPopMatrix(); + + glDisable(GL_CLIP_PLANE0); + DrawColorBar (minval, maxval, logscale); + + if (vispar.drawcoordinatecross) + DrawCoordinateCross (); + DrawNetgenLogo (); + + glFinish(); + + /* + if (lock) + { + lock -> UnLock(); + delete lock; + } + */ + mem_lock.UnLock(); + } + + + + static void 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]; + } + } + } + + + static void 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) + { + int i, j, k; + + 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); + + + const SolData * sol = NULL; + const SolData * vsol = NULL; + + if (scalfunction != -1) + sol = soldata[scalfunction]; + if (vecfunction != -1) + vsol = soldata[vecfunction]; + + if (mesh->GetTimeStamp () > solutiontimestamp) + { + sol = NULL; + vsol = NULL; + } + + if (!autoscale || scalfunction == -1) + { + 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; + } + } + + + if (surfellist) + glDeleteLists (surfellist, 1); + + surfellist = glGenLists (1); + glNewList (surfellist, GL_COMPILE); + + DrawSurfaceElements(); + + glEndList (); + + + if (linelist) + glDeleteLists (linelist, 1); + + linelist = glGenLists (1); + glNewList (linelist, GL_COMPILE); + + DrawSurfaceElementLines(); + + glEndList (); + + surfeltimestamp = max2 (solutiontimestamp, mesh->GetTimeStamp()); + + // cout << "minval = " << minval << " maxval = " << maxval << endl; + } + + + + + 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) + { + // lock->UnLock(); + mesh->BuildElementSearchTree(); + // lock->Lock(); + } + + if (clipplanelist) + glDeleteLists (clipplanelist, 1); + + + clipplanelist = glGenLists (1); + glNewList (clipplanelist, GL_COMPILE); + + if (vispar.clipenable && clipsolution == 1 && sol) + { + glDisable(GL_CLIP_PLANE0); + + ARRAY<ClipPlaneTrig> cpt; + GetClippingPlaneTrigs (cpt); + + glNormal3d (-clipplane[0], -clipplane[1], -clipplane[2]); + + glBegin (GL_TRIANGLES); + for (i = 0; i < cpt.Size(); i++) + DrawClipPlaneTrig (sol, scalcomp, cpt[i], 2*subdivisions); + glEnd(); + + glEnable(GL_CLIP_PLANE0); + } + + + if (vispar.clipenable && clipsolution == 2 && vsol) + { + if (autoscale) + GetMinMax (vecfunction, 0, minval, maxval); + + + ARRAY<ClipPlanePoint> cpp; + GetClippingPlaneGrid (cpp); + + for (i = 0; i < cpp.Size(); i++) + { + const ClipPlanePoint & p = cpp[i]; + double values[6]; + Vec3d v; + + GetValues (vsol, p.elnr, p.lam1, p.lam2, p.lam3, values); + RealVec3d (values, v, vsol->iscomplex, imag_part); + + double val = v.Length(); + + if (val > 1e-10 * maxval) + { + v *= (rad / val / gridsize * 0.5); + + SetOpenGlColor (val, minval, maxval, logscale); + DrawCone (p.p, p.p+v, rad / gridsize * 0.2); + } + } + } + + 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]; + + SurfaceElementIndex sei; + glBegin (GL_LINES); + int nse = mesh->GetNSE(); + if (sol) + for (sei = 0; sei <= nse; sei++) + { + const Element2d & el = (*mesh)[sei]; + + if (el.GetType() == TRIG || el.GetType() == TRIG6) + { + Point<3> lp1, lp2, lp3; + if (!mesh->GetCurvedElements().IsHighOrder()) + { + 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; + + values[ii] = GetSurfValue (sol, sei, x, y, scalcomp); + Point<2> xref(x,y); + + if (mesh->GetCurvedElements().IsHighOrder()) + mesh->GetCurvedElements(). + CalcSurfaceTransformation (xref, sei, points[ii]); + else + points[ii] = lp3 + x * (lp1-lp3) + y * (lp2-lp3); + + if (deform) + { + Vec<3> def; + GetSurfDeformation (sei, x, y, def); + points[ii] += def; + } + ii++; + } + + ii = 0; + for (iy = 0; iy < n; iy++) + { + for (ix = 0; ix < n-iy; ix++) + { + double x = double(ix) / n; + double y = double(iy) / n; + + int index[] = { ii, ii+1, ii+n-iy+1, + ii+1, ii+n-iy+2, ii+n-iy+1 }; + + int np = (ix == n-iy-1) ? 3 : 6; + + DrawIsoLines (points[index[0]], points[index[1]], points[index[2]], + values[index[0]], values[index[1]], values[index[2]], + minval, maxval, numisolines); + if (np == 6) + DrawIsoLines (points[index[3]], points[index[4]], points[index[5]], + values[index[3]], values[index[4]], values[index[5]], + minval, maxval, numisolines); + ii++; + } + ii++; + } + /* + double val1, val2, val3; + val1 = GetSurfValue (sol, sei, 1, 0, scalcomp); + val2 = GetSurfValue (sol, sei, 0, 1, scalcomp); + val3 = GetSurfValue (sol, sei, 0, 0, scalcomp); + */ + } + } + + if (vispar.clipenable && clipsolution == 1 && sol) + { + glDisable(GL_CLIP_PLANE0); + + ARRAY<ClipPlaneTrig> cpt; + GetClippingPlaneTrigs (cpt); + + glNormal3d (-clipplane[0], -clipplane[1], -clipplane[2]); + + if (numisolines) + for (i = 0; i < cpt.Size(); i++) + { + const ClipPlaneTrig & trig = cpt[i]; + double vali[3]; + for (j = 0; j < 3; j++) + vali[j] = GetValue (sol, trig.elnr, + trig.points[j].lami(0), + trig.points[j].lami(1), + trig.points[j].lami(2), scalcomp); + + DrawIsoLines (trig.points[0].p, + trig.points[1].p, + trig.points[2].p, + vali[0], vali[1], vali[2], minval, maxval, numisolines); + } + glEnable(GL_CLIP_PLANE0); + } + glEnd(); + + glEndList (); + } + + clipplanetimestamp = max2 (vispar.clipplanetimestamp, solutiontimestamp); + } + + + void VisualSceneSolution :: BuildFieldLinesPlot () + { + if (fieldlinestimestamp >= solutiontimestamp) + return; + fieldlinestimestamp = solutiontimestamp; + + + if (fieldlineslist) + glDeleteLists (fieldlineslist, num_fieldlineslists); + + if (vecfunction == -1) + return; + + + const SolData * vsol = soldata[vecfunction]; + + num_fieldlineslists = (vsol -> iscomplex) ? 100 : 1; + + Point3d pmin, pmax; + mesh->GetBox (pmin, pmax); + double lami[3]; + int i; + + + fieldlineslist = glGenLists (num_fieldlineslists); + + for (int ln = 0; ln < num_fieldlineslists; ln++) + { + glNewList (fieldlineslist + ln, GL_COMPILE); + + double phi = 2*M_PI*ln / num_fieldlineslists; + double phaser = cos(phi); + double phasei = sin(phi); + + for (i = 1; i <= num_fieldlines / num_fieldlineslists+1; i++) + { + Point3d p (pmin.X() + double (rand()) / RAND_MAX * (pmax.X()-pmin.X()), + pmin.Y() + double (rand()) / RAND_MAX * (pmax.Y()-pmin.Y()), + pmin.Z() + double (rand()) / RAND_MAX * (pmax.Z()-pmin.Z())); + + ElementIndex elnr = mesh->GetElementOfPoint (p, lami)-1; + (*testout) << "p = " << p << "; elnr = " << elnr << endl; + if (elnr != -1) + { + Vec3d v; + double values[6]; + GetValues (vsol, elnr, lami[0], lami[1], lami[2], values); + RealVec3d (values, v, vsol->iscomplex, phaser, phasei); + + double val = v.Length(); + + if (!fieldlines_randomstart || + (double (rand()) / RAND_MAX) < (val / maxval)) + { + int i; + Point3d p0 = p; + v *= (rad / val * 0.02); + SetOpenGlColor (val, minval, maxval, logscale); + + Point3d p2 = p + v; + cout << " p " << p << endl; + DrawCylinder (p, p2, rad * 0.003); + p = p2; + + for(i=0;i<20;i++) + { + ElementIndex elnr = mesh->GetElementOfPoint (p, lami)-1; + + if (elnr != -1) + { + GetValues (vsol, elnr, lami[0], lami[1], lami[2], values); + RealVec3d (values, v, vsol->iscomplex, phaser, phasei); + val = v.Length(); + v *= (rad / val * 0.02); + + SetOpenGlColor (val, minval, maxval, logscale); + p2 = p +v; + DrawCylinder (p, p2, rad * 0.003); + p = p2; + } + else break; + } + p=p0; + for(i=0;i<20;i++) + { + ElementIndex elnr = mesh->GetElementOfPoint (p, lami)-1; + + if (elnr != -1) + { + GetValues (vsol, elnr, lami[0], lami[1], lami[2], values); + RealVec3d (values, v, vsol->iscomplex, phaser, phasei); + + val = v.Length(); + v *= (rad / val * 0.02); + + SetOpenGlColor (val, minval, maxval, logscale); + p2 = p - v; + DrawCylinder (p, p2, rad * 0.003); + p = p2; + } + else break; + } + } + } + } + glEndList (); + } + } + + + + void VisualSceneSolution :: DrawSurfaceElements () + { + int j, k; + SurfaceElementIndex sei; + + const SolData * sol = NULL; + const SolData * vsol = NULL; + + if (scalfunction != -1) + sol = soldata[scalfunction]; + if (vecfunction != -1) + vsol = soldata[vecfunction]; + + if (mesh->GetTimeStamp () > solutiontimestamp) + { + sol = NULL; + vsol = NULL; + } + + glLineWidth (1.0f); + + if (!sol || !sol->draw_surface) + glDisable (GL_TEXTURE_1D); + + + Point<3> points[1100]; + Vec<3> nvs[1100]; + double values[1100]; + + glBegin (GL_TRIANGLES); + int nse = mesh->GetNSE(); + + glColor3f (0.4, 0.4, 0.4); + + for (sei = 0; sei < nse; sei++) + { + Element2d & el = (*mesh)[sei]; + + if (el.GetType() == TRIG || el.GetType() == TRIG6) + { + Point<3> p1, p2, p3; + if (!mesh->GetCurvedElements().IsHighOrder()) + { + GetPointDeformation (el[0]-1, p1, sei); + GetPointDeformation (el[1]-1, p2, sei); + GetPointDeformation (el[2]-1, p3, sei); + } + + 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; + + if (sol && sol->draw_surface) + values[ii] = GetSurfValue (sol, sei, x, y, scalcomp); + + Point<2> xref(x,y); + Mat<3,2> dxdxi; + + if (mesh->GetCurvedElements().IsHighOrder()) + { + mesh->GetCurvedElements(). + CalcSurfaceTransformation (xref, sei, points[ii], dxdxi); + nvs[ii] = Cross (dxdxi.Col(0), dxdxi.Col(1)); + nvs[ii].Normalize(); + } + else + { + points[ii] = p3 + x * (p1-p3) + y * (p2-p3); + nvs[ii] = Cross (p2-p1, p3-p1); + nvs[ii].Normalize(); + } + + if (deform) + { + Vec<3> def; + GetSurfDeformation (sei, x, y, def); + points[ii] += def; + } + ii++; + } + + ii = 0; + + for (iy = 0; iy < n; iy++) + { + for (ix = 0; ix < n-iy; ix++) + { + double x = double(ix) / n; + double y = double(iy) / n; + + int index[] = { ii, ii+1, ii+n-iy+1, + ii+1, ii+n-iy+2, ii+n-iy+1 }; + + int np = (ix == n-iy-1) ? 3 : 6; + for (int j = 0; j < np; j++) + { + if (sol && sol->draw_surface) + SetOpenGlColor (values[index[j]], minval, maxval, logscale); + glNormal3dv (&nvs[index[j]](0)); + glVertex3dv (points[index[j]]); + } + ii++; + } + ii++; + } + } + } + glEnd (); + + + + + + + glBegin (GL_QUADS); + for (sei = 0; sei < nse; sei++) + { + const Element2d & el = (*mesh)[sei]; + + if (el.GetType() == QUAD || el.GetType() == QUAD6) + { + Point<3> lpi[4]; + for (k = 0; k < 4; k++) + GetPointDeformation (el[k]-1, lpi[k]); + Vec<3> vx = lpi[1]-lpi[0]; + Vec<3> vy = lpi[3]-lpi[0]; + Vec<3> vtwist = (lpi[0]-lpi[1]) + (lpi[2]-lpi[3]); + Vec<3> nv = Cross (lpi[1]-lpi[0], Center (lpi[2],lpi[3]) - lpi[0]); + nv.Normalize(); + glNormal3dv (nv); + + + int n = 1 << subdivisions; + int ii = 0; + int ix, iy; + for (iy = 0; iy <= n; iy++) + for (ix = 0; ix <= n; ix++) + { + double x = double(ix) / n; + double y = double(iy) / n; + + Point<2> xref(x,y); + Mat<3,2> dxdxi; + + if (sol && sol->draw_surface) + values[ii] = GetSurfValue (sol, sei, x, y, scalcomp); + + + if (mesh->GetCurvedElements().IsHighOrder()) + { + mesh->GetCurvedElements(). + CalcSurfaceTransformation (xref, sei, points[ii], dxdxi); + nvs[ii] = Cross (dxdxi.Col(0), dxdxi.Col(1)); + nvs[ii].Normalize(); + } + else + { + points[ii] = lpi[0] + x * vx + y * vy + x*y * vtwist; + nvs[ii] = Cross (vx, vy); + nvs[ii].Normalize(); + } + + if (deform) + { + Vec<3> def; + GetSurfDeformation (sei, x, y, def); + points[ii] += def; + } + + // points[ii] = lpi[0] + x * vx + y * vy; + ii++; + } + + ii = 0; + for (iy = 0; iy < n; iy++) + { + for (ix = 0; ix < n; ix++) + { + double x = double(ix) / n; + double y = double(iy) / n; + + int index[] = { ii, ii+1, ii+n+2, ii+n+1 }; + + for (int j = 0; j < 4; j++) + { + if (sol && sol->draw_surface) + SetOpenGlColor (values[index[j]], minval, maxval, logscale); + glNormal3dv (&nvs[index[j]](0)); + glVertex3dv (points[index[j]]); + } + ii++; + } + ii++; + } + } + } + glEnd(); + + if (usetexture) + glEnable (GL_TEXTURE_1D); + + } + + + // Bernstein Pol B_{n,i}(x) = n! / i! / (n-i)! (1-x)^{n-i} x^i + static double Bernstein (int n, int i, double x) + { + int j; + double val = 1; + for (j = 1; j <= i; j++) + val *= x / j; + for (j = 1; j <= n-i; j++) + val *= (1-x) / j; + for (j = 1; j <= n; j++) + val *= j; + return val; + } + + void VisualSceneSolution :: DrawSurfaceElementLines () + { + int i, j, k, l; + SurfaceElementIndex sei; + + /* + int p = 4; + DenseMatrix mat(p+1,p+1), invmat(p+1,p+1); + for (i = 0; i <= p; i++) + for (j = 0; j <= p; j++) + mat.Elem(i+1,j+1) = Bernstein(p, i, double(j)/p); + CalcIo +nverse (mat, invmat); + */ + + glLineWidth (1.0f); + glNormal3d (1, 0, 0); + + int nse = mesh->GetNSE(); + + for (sei = 0; sei < nse; sei++) + { + Element2d & el = (*mesh)[sei]; + + int nv; + if (el.GetType() == TRIG || el.GetType() == TRIG6) + nv = 3; + else + nv = 4; + + Point<3> p1, p2, p3, p4; + GetPointDeformation (el[0]-1, p1, sei); + GetPointDeformation (el[1]-1, p2, sei); + GetPointDeformation (el[2]-1, p3, sei); + if (nv == 4) + GetPointDeformation (el[3]-1, p4, sei); + + + // glBegin (GL_LINE_LOOP); + int n = 1 << subdivisions; + // n = p; + + int ii = 0; + int ix, iy; + Point<3> pnt; + + for (k = 0; k < nv; k++) + { + Point<2> p0; + Vec<2> vtau; + if (nv == 3) + switch (k) + { + case 0: + p0 = Point<2> (0,0); + vtau = Vec<2> (1,0); + break; + case 1: + p0 = Point<2> (1,0); + vtau = Vec<2> (-1,1); + break; + case 2: + p0 = Point<2> (0,1); + vtau = Vec<2> (0,-1); + break; + } + else + switch (k) + { + case 0: + p0 = Point<2> (0,0); + vtau = Vec<2> (1,0); + break; + case 1: + p0 = Point<2> (1,0); + vtau = Vec<2> (0,1); + break; + case 2: + p0 = Point<2> (1,1); + vtau = Vec<2> (-1,0); + break; + case 3: + p0 = Point<2> (0,1); + vtau = Vec<2> (0,-1); + break; + } + + + glBegin (GL_LINE_STRIP); + Point<3> pts[33], pts2[33]; + if (n > 32) cerr << "too many subdivisions, code 433425" << endl; + + for (ix = 0; ix <= n; ix++) + { + Point<2> p = p0 + (double(ix) / n) * vtau; + double x = p(0); + double y = p(1); + Point<2> xref(x,y); + + if (mesh->GetCurvedElements().IsHighOrder()) + mesh->GetCurvedElements(). + CalcSurfaceTransformation (xref, sei, pnt); + else + { + if (nv == 3) + pnt = p3 + x * (p1-p3) + y * (p2-p3); + else + pnt = p1 + x * (p2-p1) + y * (p4-p1) + x*y * ( (p1-p2)+(p3-p4) ); + } + + if (deform) + { + Vec<3> def; + GetSurfDeformation (sei, x, y, def); + pnt += def; + } + + glVertex3dv (pnt); + + pts[ix] = pnt; + } + glEnd (); + + + + /* + // convert from point-values to Bernstein basis + for (i = 0; i < 3; i++) + for (j = 0; j <= p; j++) + { + pts2[j](i) = 0; + for (l = 0; l <= p; l++) + pts2[j](i) += invmat(l,j) * pts[l](i); + } + + + glMap1d(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, n+1, &pts2[0](0)); + glEnable(GL_MAP1_VERTEX_3); + + int steps = 1 << subdivisions; + +// glBegin (GL_LINE_STRIP); +// for (int hi = 0; hi <= 10; hi++) +// glEvalCoord1d (double(hi)/10.0); +// glEnd (); + + glMapGrid1d (steps, 0.0, 1.0); + glEvalMesh1(GL_LINE, 0, steps); + glDisable(GL_MAP1_VERTEX_3); + */ + } + + } + + } + + + + + + + + + + + + + + + + + + + + +void VisualSceneSolution :: DrawSurfaceVectors () +{ + int j, k; + int dir, dir1, dir2; + SurfaceElementIndex sei; + + const SolData * vsol = NULL; + + 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); + + double s, t; + + // draw surface cones + // if (0) + /* + if (vsol->soltype==SOL_SURFACE_ELEMENT || + vsol->soltype==SOL_SURFACE_NONCONTINUOUS || + vsol->soltype==SOL_VIRTUALFUNCTION) + */ + if (vsol->draw_surface && showsurfacesolution) + { + int nse = mesh->GetNSE(); + for (sei = 0; sei < nse; sei++) + { + const Element2d & el = (*mesh)[sei]; + + if (el.GetType() != TRIG && el.GetType() != TRIG6) continue; + + Point<3> lp[3]; + Point<2> p2d[3]; + /* + for (k = 0; k < 3; k++) + lp[k] = mesh->Point (el[k]); + */ + lp[0] = mesh->Point(el[2]); + lp[1] = mesh->Point(el[0]); + lp[2] = mesh->Point(el[1]); + + + 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; + + + + for (s = 0; s <= 1; s += 1.0 / gridsize) + if (s >= minx2d && s <= maxx2d) + for (t = 0; t <= 1; 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]; + 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) + v(2) = 0; + + double val = v.Length(); + SetOpenGlColor (val, minval, maxval, logscale); + + if (val > 1e-10 * maxval) + v *= (rad / val / gridsize * 0.5); + DrawCone (cp, cp+4*v, 0.8*rad / gridsize); + + /* + v /= val; + + glPushMatrix(); + glTranslated (cp(0), cp(1), cp(2)); + + double l = 2*rad/gridsize; + double r = 0.8*rad/gridsize; + glScaled (l, l, l); + + double phi = acos (v(2)); + glRotated (-180/M_PI*phi, v(1), -v(0), 0); + + glCallList (cone_list); + glPopMatrix(); + */ + } + } + } + } +} + + + + +void VisualSceneSolution :: +DrawIsoLines (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + double val1, double val2, double val3, + double minval, double maxval, int n) +{ + 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 Point3d & p1, + const Point3d & p2, + const Point3d & p3, + const Point3d & p4, + double val1, double val2, double val3, double val4, + double minval, double maxval, int n) +{ + if (val1 > val2) + DrawIsoLines2 (p2, p1, p3, p4, val2, val1, val3, val4, minval, maxval, n); + if (val3 > val4) + DrawIsoLines2 (p1, p2, p4, p3, val1, val2, val4, val3, minval, maxval, n); + + 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+1; 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) + { + Point3d lp1 = p1 + lam1 * Vec3d (p1, p2); + Point3d lp2 = p3 + lam2 * Vec3d (p3, p4); + glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); + glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); + glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); + glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); + } + } +} + + + + + + + +void VisualSceneSolution :: +GetMinMax (int funcnr, int comp, double & minv, double & maxv) const +{ + int i, j; + const SolData * sol; + double val; + + bool hasit = 0; + 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++) + { + double val = GetValue (sol, i, 0.333, 0.333, 0.333, comp); + if (val > maxv || !hasit) + maxv = val; + if (val < minv || !hasit) + minv = val; + hasit = 1; + } + } + if (sol->draw_surface) + { + int nse = mesh->GetNSE(); + for (int i = 0; i < nse; i++) + { + double val = GetSurfValue (sol, i, 0.333, 0.333, comp); + if (val > maxv || !hasit) + maxv = val; + if (val < minv || !hasit) + minv = val; + hasit = 1; + } + } + } +} + + + + + +void VisualSceneSolution :: +GetValues (const SolData * data, ElementIndex elnr, + double lam1, double lam2, double lam3, + double * values) const +{ + switch (data->soltype) + { + case SOL_VIRTUALFUNCTION: + { + bool ok = + data->solclass->GetValue (elnr, lam1, lam2, lam3, values); + break; + } + default: + { + for (int i = 0; i < data->components; i++) + values[i] = GetValue (data, elnr, lam1, lam2, lam3, i+1); + } + } +} + + +double VisualSceneSolution :: +GetValue (const SolData * data, ElementIndex elnr, + double lam1, double lam2, double lam3, + int comp) const +{ + if (comp == 0) + { + double val = 0; + ArrayMem<double,20> values(data->components); + GetValues (data, elnr, lam1, lam2, lam3, &values[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; + switch (data->components) + { + case 1: d = 1; break; + case 3: d = 2; break; + case 6: d = 3; break; + } + int ci; + for (ci = 0; ci < d; ci++) + val += sqr (values[ci]); + for (ci = d; ci < data->components; ci++) + val += 2*sqr (values[ci]); + val = sqrt (val); + break; + } + + case FUNC_MISES: + { + int d; + 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; + 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; + } + + + switch (data->soltype) + { + case SOL_VIRTUALFUNCTION: + { + double values[20]; + bool ok = data->solclass->GetValue (elnr, lam1, lam2, lam3, values); + + if (ok) + return values[comp-1]; + else + return 0; + } + case SOL_NODAL: + { + const Element & el = (*mesh)[elnr]; + + double lami[8]; + int np, i; + double val = 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; + } + } + + for (i = 0; i < np; i++) + val += lami[i] * data->data[(el[i]-1) * data->dist + comp-1]; + + return val; + } + + case SOL_ELEMENT: + { + return data->data[elnr * data->dist + comp-1]; + } + + case SOL_SURFACE_ELEMENT: + return 0; + + case SOL_NONCONTINUOUS: + { + const Element & el = (*mesh)[elnr]; + + double lami[8]; + int np, i; + double val = 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 (i = 0; i < np; i++) + val += lami[i] * data->data[(base+i) * data->dist + comp-1]; + + return val; + } + + case SOL_MARKED_ELEMENTS: + return (*mesh)[elnr].TestRefinementFlag(); + + case SOL_ELEMENT_ORDER: + return (*mesh)[elnr].GetOrder(); + } + return 0; +} + + + + +void VisualSceneSolution :: +GetSurfValues (const SolData * data, SurfaceElementIndex selnr, + double lam1, double lam2, + double * values) const +{ + switch (data->soltype) + { + case SOL_VIRTUALFUNCTION: + { + bool ok = + data->solclass->GetSurfValue (selnr, lam1, lam2, values); + break; + } + default: + { + for (int i = 0; i < data->components; i++) + values[i] = GetSurfValue (data, selnr, lam1, lam2, i+1); + } + } +} + + + +double VisualSceneSolution :: +GetSurfValue (const SolData * data, SurfaceElementIndex selnr, + double lam1, double lam2, + int comp) const +{ + if (comp == 0) + { + double val = 0; + ArrayMem<double,20> values(data->components); + GetSurfValues (data, selnr, lam1, lam2, &values[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; + switch (data->components) + { + case 1: d = 1; break; + case 3: d = 2; break; + case 6: d = 3; break; + } + int ci; + for (ci = 0; ci < d; ci++) + val += sqr (values[ci]); + for (ci = d; ci < data->components; ci++) + val += 2*sqr (values[ci]); + val = sqrt (val); + break; + } + + case FUNC_MISES: + { + int d; + 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; + 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; + + + /* + int ci; + double val = 0; + for (ci = 1; ci <= data->components; ci++) + val += sqr (GetSurfValue (data, selnr, lam1, lam2, ci)); + return sqrt (val); + */ + } + + + switch (data->soltype) + { + case SOL_VIRTUALFUNCTION: + { + double values[20]; + bool ok = + data->solclass->GetSurfValue (selnr, lam1, lam2, values); + if (ok) + return values[comp-1]; + else + return 0; + } + + + case SOL_NODAL: + { + const Element2d & el = (*mesh)[selnr]; + + double lami[8]; + int np, i; + double 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 val; + } + + case SOL_ELEMENT: + { + int el1, el2; + mesh->GetTopology().GetSurface2VolumeElement (selnr+1, el1, el2); + el1--; + + return data->data[el1 * data->dist+comp-1]; + } + + case SOL_NONCONTINUOUS: + { + return 0; + } + + case SOL_SURFACE_ELEMENT: + { + return data->data[selnr * data->dist + comp-1]; + } + + case SOL_SURFACE_NONCONTINUOUS: + { + const Element2d & el = (*mesh)[selnr]; + + double lami[8]; + int np, i; + double 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; + } + } + 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; + } + } + break; + } + } + + int base; + if (order == 1) + base = 4 * selnr; + else + base = 9 * selnr; + + for (i = 0; i < np; i++) + { + val += lami[i] * data->data[(base+i) * data->dist + comp-1]; + } + return val; + } + + case SOL_MARKED_ELEMENTS: + return (*mesh)[selnr].TestRefinementFlag(); + + case SOL_ELEMENT_ORDER: + return (*mesh)[selnr].GetOrder(); + + } + return 0; +} + + +void VisualSceneSolution :: +GetDeformation (ElementIndex elnr, double lam1, double lam2, double lam3, + Vec<3> & def) const +{ + if (deform && vecfunction != -1) + { + GetValues (soldata[vecfunction], elnr, lam1, lam2, lam3, &def(0)); + def *= scaledeform; + + if (soldata[vecfunction]->dist == 2) def(2) = 0; + } + else + def = 0; +} + + +void VisualSceneSolution :: +GetSurfDeformation (SurfaceElementIndex elnr, double lam1, double lam2, + Vec<3> & def) const +{ + if (deform && vecfunction != -1) + { + GetSurfValues (soldata[vecfunction], elnr, lam1, lam2, &def(0)); + def *= scaledeform; + + if (soldata[vecfunction]->dist == 2) def(2) = 0; + } + else + def = 0; +} + +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) +{ + // cout << "get clipplane trigs" << endl; + + int ii, j, k, l; + ElementIndex ei; + // int np = mesh->GetNV(); + int np = mesh->GetNP(); + int ne = mesh->GetNE(); + + ARRAY<double> nodevals(np); + + for (int i = 0; i < np; i++) + { + Point<3> p; + GetPointDeformation(i, p); + nodevals[i] = + p(0) * clipplane[0] + + p(1) * clipplane[1] + + p(2) * clipplane[2] + + clipplane[3]; + } + + 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<Point3d> pointsloc; + + for (ei = 0; ei < ne; ei++) + { + // const Element & el = mesh->VolumeElement(i); + + (*mesh)[ei].GetTets (loctets); + (*mesh)[ei].GetTetsLocal (loctetsloc); + // (*mesh)[ei].GetNodesLocal (pointsloc); + (*mesh)[ei].GetNodesLocalNew (pointsloc); + + for (ii = 0; ii < loctets.Size(); ii++) + { + const Element & el = loctets[ii]; + + for (j = 0; j < 4; j++) + nodevali[j] = nodevals.Get(el[j]); + + cntce = 0; + for (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, p2; + GetPointDeformation (el[lpi1]-1, p1); + GetPointDeformation (el[lpi2]-1, p2); + + edgep[j] = p1 + (1-edgelam[j]) * (p2-p1); + + cntce++; + cpe3 = cpe2; + cpe2 = cpe1; + cpe1 = j; + if (cntce >= 3) + { + ClipPlaneTrig cpt; + cpt.elnr = ei; + + for (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 = pointsloc.Get (loctetsloc[ii][pi1]); + Point<3> p2 = pointsloc.Get (loctetsloc[ii][pi2]); + for (l = 0; l < 3; l++) + cpt.points[k].lami(l) = + edgelam[ednr] * p1(l) + + (1-edgelam[ednr]) * p2(l); + } + + trigs.Append (cpt); + } + } + } + } + + } +} + +void VisualSceneSolution :: GetClippingPlaneGrid (ARRAY<ClipPlanePoint> & pts) +{ + int i, j, k; + int np = mesh->GetNV(); + int ne = mesh->GetNE(); + + 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(); + 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); + + int elnr; + double lami[3]; + + for (xi1 = xi1mid-rad; xi1 <= xi1mid+rad; xi1 += rad / gridsize) + for (xi2 = xi2mid-rad; xi2 <= xi2mid+rad; xi2 += rad / gridsize) + { + Point3d hp = p + xi1 * t1 + xi2 * t2; + + elnr = mesh->GetElementOfPoint (hp, lami)-1; + + if (elnr != -1) + { + ClipPlanePoint cpp; + cpp.p = hp; + cpp.elnr = elnr; + cpp.lam1 = lami[0]; + cpp.lam2 = lami[1]; + cpp.lam3 = lami[2]; + pts.Append (cpp); + } + } +}; + + + +void VisualSceneSolution :: +SetOpenGlColor(double h, double hmin, double hmax, int logscale) +{ + double value; + + if (!logscale) + value = (h - hmin) / (hmax - hmin); + else + { + if (hmax <= 0) hmax = 1; + if (hmin <= 0) hmin = 1e-4 * hmax; + value = (log(fabs(h)) - log(hmin)) / (log(hmax) - log(hmin)); + } + + if (!invcolor) + value = 1 - value; + + if (usetexture) + { + glTexCoord1f ( 0.999 * value + 0.001); + return; + }; + + if (value > 1) value = 1; + if (value < 0) value = 0; + + value *= 4; + + 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]; + int j; + for (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 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); + double phi; + 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); + double phi; + 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) +{ + ; +} + + +void VisualSceneSolution :: +DrawClipPlaneTrig (const SolData * sol, + int comp, + const ClipPlaneTrig & trig, + int level) +{ + int j; + if (level <= 0) + for (j = 0; j < 3; j++) + { + Point<3> p; + if (mesh->GetCurvedElements().IsHighOrder()) + { + mesh->GetCurvedElements(). + CalcElementTransformation (trig.points[j].lami, trig.elnr, p); + } + else + p = trig.points[j].p; + + if (deform) + { + Vec<3> def; + GetDeformation (trig.elnr, + trig.points[j].lami(0), + trig.points[j].lami(1), + trig.points[j].lami(2), def); + p += def; + } + + double val = + GetValue (sol, trig.elnr, + trig.points[j].lami(0), + trig.points[j].lami(1), + trig.points[j].lami(2), scalcomp); + + SetOpenGlColor (val, minval, maxval, logscale); + glVertex3dv (p); + } + else + { + Point<3> newp = Center (trig.points[1].p, trig.points[2].p); + Point<3> newlami = Center (trig.points[1].lami, trig.points[2].lami); + ClipPlaneTrig t1, t2; + t1.elnr = t2.elnr = trig.elnr; + t1.points[0].p = newp; + t1.points[0].lami = newlami; + t1.points[1] = trig.points[2]; + t1.points[2] = trig.points[0]; + t2.points[0].p = newp; + t2.points[0].lami = newlami; + t2.points[1] = trig.points[0]; + t2.points[2] = trig.points[1]; + DrawClipPlaneTrig (sol, comp, t1, level-1); + DrawClipPlaneTrig (sol, comp, t2, level-1); + } +} + + + + + +int Ng_Vis_Set (ClientData clientData, + Tcl_Interp * interp, + int argc, tcl_const char *argv[]) + +{ + int i; + if (argc >= 2) + { + if (strcmp (argv[1], "parameters") == 0) + { + vssolution.imag_part = + atoi (Tcl_GetVar (interp, "visoptions.imaginary", 0)); + vssolution.usetexture = + atoi (Tcl_GetVar (interp, "visoptions.usetexture", 0)); + vssolution.invcolor = + atoi (Tcl_GetVar (interp, "visoptions.invcolor", 0)); + + vssolution.clipsolution = 0; + + if (strcmp (Tcl_GetVar (interp, "visoptions.clipsolution", 0), + "scal") == 0) + vssolution.clipsolution = 1; + if (strcmp (Tcl_GetVar (interp, "visoptions.clipsolution", 0), + "vec") == 0) + vssolution.clipsolution = 2; + + const char * scalname = + Tcl_GetVar (interp, "visoptions.scalfunction", 0); + const char * vecname = + Tcl_GetVar (interp, "visoptions.vecfunction", 0); + + vssolution.scalfunction = -1; + vssolution.vecfunction = -1; + + for (i = 0; i < vssolution.soldata.Size(); i++) + { + if (strlen (vssolution.soldata[i]->name) == + strlen (scalname)-2 && + strncmp (vssolution.soldata[i]->name, scalname, + strlen (scalname)-2) == 0) + { + vssolution.scalfunction = i; + vssolution.scalcomp = atoi (scalname + strlen(scalname)-1); + } + if (strcmp (vssolution.soldata[i]->name, vecname) == 0) + vssolution.vecfunction = i; + } + + + const char * evalname = + Tcl_GetVar (interp, "visoptions.evaluate", 0); + + 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", 0)); + + vssolution.autoscale = + atoi (Tcl_GetVar (interp, "visoptions.autoscale", 0)); + + /* + vssolution.linear_colors = + atoi (Tcl_GetVar (interp, "visoptions.lineartexture", 0)); + */ + vssolution.logscale = + atoi (Tcl_GetVar (interp, "visoptions.logscale", 0)); + + vssolution.mminval = + atof (Tcl_GetVar (interp, "visoptions.mminval", 0)); + vssolution.mmaxval = + atof (Tcl_GetVar (interp, "visoptions.mmaxval", 0)); + + vssolution.showclipsolution = + atoi (Tcl_GetVar (interp, "visoptions.showclipsolution", 0)); + vssolution.showsurfacesolution = + atoi (Tcl_GetVar (interp, "visoptions.showsurfacesolution", 0)); + vssolution.lineartexture = + atoi (Tcl_GetVar (interp, "visoptions.lineartexture", 0)); + vssolution.numtexturecols = + atoi (Tcl_GetVar (interp, "visoptions.numtexturecols", 0)); + + vssolution.draw_fieldlines = + atoi (Tcl_GetVar (interp, "visoptions.drawfieldlines", 0)); + vssolution.num_fieldlines = + atoi (Tcl_GetVar (interp, "visoptions.numfieldlines", 0)); + vssolution.fieldlines_randomstart = + atoi (Tcl_GetVar (interp, "visoptions.fieldlinesrandomstart", 0)); + + + vssolution.deform = + atoi (Tcl_GetVar (interp, "visoptions.deformation", 0)); + vssolution.scaledeform = + atof (Tcl_GetVar (interp, "visoptions.scaledeform1", 0)) * + atof (Tcl_GetVar (interp, "visoptions.scaledeform2", 0)); + + + if (atoi (Tcl_GetVar (interp, "visoptions.isolines", 0))) + vssolution.numisolines = atoi (Tcl_GetVar (interp, "visoptions.numiso", 0)); + else + vssolution.numisolines = 0; + + vssolution.subdivisions = + atoi (Tcl_GetVar (interp, "visoptions.subdivisions", 0)); + vssolution.UpdateSolutionTimeStamp(); + } + + if (argc >= 3 && strcmp (argv[1], "time") == 0) + { + vssolution.time = double (atoi (argv[2])) / 1000; + // cout << "time = " << vssolution.time << endl; + } + + } + return TCL_OK; +} + +int Ng_Vis_Field (ClientData clientData, + Tcl_Interp * interp, + int argc, tcl_const char *argv[]) +{ + int i; + static 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; +} +} diff --git a/Netgen/libsrc/visualization/vssolution.hpp b/Netgen/libsrc/visualization/vssolution.hpp new file mode 100644 index 0000000000..8a63ffd6ba --- /dev/null +++ b/Netgen/libsrc/visualization/vssolution.hpp @@ -0,0 +1,212 @@ +#ifndef FILE_VSSOLUTION +#define FILE_VSSOLUTION + + + + + +extern int Ng_Vis_Set (ClientData clientData, + Tcl_Interp * interp, + int argc, tcl_const char *argv[]); + +class VisualSceneSolution : public VisualScene +{ + class ClipPlaneTrig + { + public: + struct ps + { + Point<3> lami; + Point<3> p; + }; + ps points[3]; + ElementIndex elnr; + }; + + class ClipPlanePoint + { + public: + ElementIndex elnr; + double lam1, lam2, lam3; + Point<3> p; + }; + + + int surfellist; + int linelist; + int clipplanelist; + int isolinelist; + int surface_vector_list; + int cone_list; + + bool draw_fieldlines; + int num_fieldlines; + bool fieldlines_randomstart; + int fieldlineslist; + int num_fieldlineslists; + + int surfeltimestamp, clipplanetimestamp, solutiontimestamp; + int fieldlinestimestamp, surface_vector_timestamp; + double minval, maxval; + + + + NgLock *lock; + +public: + + enum EvalFunc { + FUNC_ABS = 1, + FUNC_ABS_TENSOR = 2, + FUNC_MISES = 3, + FUNC_MAIN = 4 + }; + EvalFunc 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: + 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; + int clipsolution; // 0..no, 1..scal, 2..vec + int scalfunction, scalcomp, vecfunction; + int gridsize; + + int autoscale, logscale; + double mminval, mmaxval; + int numisolines; + int subdivisions; + + bool showclipsolution; + bool showsurfacesolution; + bool lineartexture; + int numtexturecols; + + // bool fieldlineplot; + double time; + + int deform; + double scaledeform; + bool imag_part; + +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); +private: + void GetMinMax (int funcnr, int comp, double & minv, double & maxv) const; + + void GetClippingPlaneTrigs (ARRAY<ClipPlaneTrig> & trigs); + 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, + double GetValue (const SolData * data, ElementIndex elnr, + double lam1, double lam2, double lam3, + int comp) const; + double GetSurfValue (const SolData * data, SurfaceElementIndex elnr, + double lam1, double lam2, + int comp) const; + void GetValues (const SolData * data, ElementIndex elnr, + double lam1, double lam2, double lam3, + double * values) const; + void GetSurfValues (const SolData * data, SurfaceElementIndex elnr, + double lam1, double lam2, + double * values) const; + + void GetDeformation (ElementIndex elnr, double lam1, double lam2, double lam3, + Vec<3> & def) const; + void GetSurfDeformation (SurfaceElementIndex selnr, double lam1, double lam2, + Vec<3> & def) const; + + void GetPointDeformation (int pnum, Point<3> & p, SurfaceElementIndex elnr = -1) const; + + /// draw elements (build lists) + void DrawSurfaceElements (); + void DrawSurfaceElementLines (); + void DrawSurfaceVectors (); + + void DrawIsoLines (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + double val1, double val2, double val3, + double minval, double maxval, int n); + + // draw isolines between lines (p1,p2) and (p3,p4) + void DrawIsoLines2 (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + const Point3d & p4, + double val1, double val2, double val3, double val4, + double minval, double maxval, int n); + + + void DrawClipPlaneTrig (const SolData * sol, + int comp, + const ClipPlaneTrig & trig, + int level); + + void SetOpenGlColor(double val, double valmin, double valmax, int logscale = 0); + + + friend int Ng_Vis_Set (ClientData clientData, + Tcl_Interp * interp, + int argc, tcl_const char *argv[]); + + + +}; + + +extern VisualSceneSolution vssolution; + + + + +#endif + diff --git a/configure b/configure index f91e58457b..4187882b6c 100755 --- a/configure +++ b/configure @@ -852,6 +852,7 @@ Optional Features: --enable-system-menubar use the system menu bar on MacOS X (default=no) --enable-parallel enable parallel version (default=no) --enable-triangle compile Triangle if available (default=yes) + --enable-netgen compile Netgen if available (default=yes) --enable-matheval compile MathEval if available (default=yes) --enable-jpeg enable JPEG support (default=yes) --enable-z enable ZLIB support (default=yes) @@ -1354,6 +1355,11 @@ fi; if test "${enable_triangle+set}" = set; then enableval="$enable_triangle" +fi; +# Check whether --enable-netgen or --disable-netgen was given. +if test "${enable_netgen+set}" = set; then + enableval="$enable_netgen" + fi; # Check whether --enable-matheval or --disable-matheval was given. if test "${enable_matheval+set}" = set; then @@ -3539,6 +3545,58 @@ else fi fi + +echo "$as_me:$LINENO: checking for ./Netgen/libsrc/meshing/meshclass.cpp" >&5 +echo $ECHO_N "checking for ./Netgen/libsrc/meshing/meshclass.cpp... $ECHO_C" >&6 +if test "${ac_cv_file___Netgen_libsrc_meshing_meshclass_cpp+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + test "$cross_compiling" = yes && + { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5 +echo "$as_me: error: cannot check for file existence when cross compiling" >&2;} + { (exit 1); exit 1; }; } +if test -r "./Netgen/libsrc/meshing/meshclass.cpp"; then + ac_cv_file___Netgen_libsrc_meshing_meshclass_cpp=yes +else + ac_cv_file___Netgen_libsrc_meshing_meshclass_cpp=no +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_file___Netgen_libsrc_meshing_meshclass_cpp" >&5 +echo "${ECHO_T}$ac_cv_file___Netgen_libsrc_meshing_meshclass_cpp" >&6 +if test $ac_cv_file___Netgen_libsrc_meshing_meshclass_cpp = yes; then + NETGEN="yes" +else + NETGEN="no" +fi + +if test "x${NETGEN}" = "xyes"; then + if test "x$enable_netgen" != "xno"; then + GMSH_DIRS="${GMSH_DIRS} Netgen" + GMSH_LIBS="${GMSH_LIBS} -lGmshNetgen" + FLAGS="-DHAVE_NETGEN ${FLAGS}" + echo "********************************************************************" + echo "You are building a version of Gmsh that contains Joachim Schoberl's" + echo "Netgen as an alternative 3D mesh generator. Netgen is distributed" + echo "under the GNU LGPL: see ./Netgen/COPYING.LIB for more info." + echo "To disable Netgen, run configure again with the --disable-netgen" + echo "option." + echo "********************************************************************" + fi +else + if test "x$enable_netgen" != "xno"; then + echo "********************************************************************" + echo "If you want to use Joachim Schoberl's Netgen as an alternative " + echo "3D mesh generator, please download Netgen from the project's" + echo "web site at http://www.hpfem.jku.at/netgen/, unpack the archive" + echo "and move the libsrc subdirectory in the ./Netgen subdirectory. Then" + echo "run ./configure again." + echo "Please note that by doing so, you agree with Netgen's licensing" + echo "requirements stated in ./Netgen/COPYING.LIB." + echo "********************************************************************" + fi +fi + + echo "$as_me:$LINENO: checking for ./MathEval/matheval.cpp" >&5 echo $ECHO_N "checking for ./MathEval/matheval.cpp... $ECHO_C" >&6 if test "${ac_cv_file___MathEval_matheval_cpp+set}" = set; then @@ -3570,6 +3628,7 @@ if test "x${MATHEVAL}" = "xyes"; then fi fi + if test "x$enable_gsl" != "xno"; then if test "x${GSL_PREFIX}" != "x"; then LDFLAGS="-L${GSL_PREFIX}/lib ${LDFLAGS}" diff --git a/configure.in b/configure.in index ed200de6cd..ed2b49ff7b 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -dnl $Id: configure.in,v 1.53 2004-06-12 18:34:31 geuzaine Exp $ +dnl $Id: configure.in,v 1.54 2004-06-26 17:58:14 geuzaine Exp $ dnl dnl Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle dnl @@ -66,6 +66,9 @@ AC_ARG_ENABLE(parallel, AC_ARG_ENABLE(triangle, AC_HELP_STRING([--enable-triangle], [compile Triangle if available (default=yes)])) +AC_ARG_ENABLE(netgen, + AC_HELP_STRING([--enable-netgen], + [compile Netgen if available (default=yes)])) AC_ARG_ENABLE(matheval, AC_HELP_STRING([--enable-matheval], [compile MathEval if available (default=yes)])) @@ -246,6 +249,37 @@ else fi fi + +dnl Check if Netgen is installed +AC_CHECK_FILE(./Netgen/libsrc/meshing/meshclass.cpp, NETGEN="yes", NETGEN="no") +if test "x${NETGEN}" = "xyes"; then + if test "x$enable_netgen" != "xno"; then + GMSH_DIRS="${GMSH_DIRS} Netgen" + GMSH_LIBS="${GMSH_LIBS} -lGmshNetgen" + FLAGS="-DHAVE_NETGEN ${FLAGS}" + echo "********************************************************************" + echo "You are building a version of Gmsh that contains Joachim Schoberl's" + echo "Netgen as an alternative 3D mesh generator. Netgen is distributed" + echo "under the GNU LGPL: see ./Netgen/COPYING.LIB for more info." + echo "To disable Netgen, run configure again with the --disable-netgen" + echo "option." + echo "********************************************************************" + fi +else + if test "x$enable_netgen" != "xno"; then + echo "********************************************************************" + echo "If you want to use Joachim Schoberl's Netgen as an alternative " + echo "3D mesh generator, please download Netgen from the project's" + echo "web site at http://www.hpfem.jku.at/netgen/, unpack the archive" + echo "and move the libsrc subdirectory in the ./Netgen subdirectory. Then" + echo "run ./configure again." + echo "Please note that by doing so, you agree with Netgen's licensing" + echo "requirements stated in ./Netgen/COPYING.LIB." + echo "********************************************************************" + fi +fi + + dnl Check for MathEval AC_CHECK_FILE(./MathEval/matheval.cpp, MATHEVAL="yes", MATHEVAL="no") if test "x${MATHEVAL}" = "xyes"; then @@ -256,6 +290,7 @@ if test "x${MATHEVAL}" = "xyes"; then fi fi + dnl Check for GSL if test "x$enable_gsl" != "xno"; then if test "x${GSL_PREFIX}" != "x"; then diff --git a/tutorial/t2.geo b/tutorial/t2.geo index 0ba1e40ed8..0de54c009e 100644 --- a/tutorial/t2.geo +++ b/tutorial/t2.geo @@ -71,10 +71,10 @@ Characteristic Length {tmp[0], 22, 2, 3, 16, 12} = lc * 4; // following volumes don't have holes and thus consist of single // surface loops: -Surface Loop(145) = {121,11,131,135,139,144}; +Surface Loop(145) = {-121,11,-131,-135,-139,-144}; Volume(146) = {145}; -Surface Loop(146) = {121,6,109,113,117,122}; +Surface Loop(146) = {121,-6,109,113,117,122}; Volume(147) = {146}; // To save all the tetrahedra discretizing the volumes 146 and 147 diff --git a/tutorial/t5.geo b/tutorial/t5.geo index 9cadb74884..fb7db01277 100644 --- a/tutorial/t5.geo +++ b/tutorial/t5.geo @@ -48,14 +48,14 @@ Line(13) = {6,2}; Line(14) = {2,1}; Line(15) = {1,3}; Line(16) = {3,7}; Line(17) = {7,2}; Line(18) = {3,4}; Line(19) = {5,1}; Line(20) = {7,8}; Line(21) = {6,14}; -Line Loop(22) = {11,19,15,18}; Plane Surface(23) = {22}; +Line Loop(22) = {-11,-19,-15,-18}; Plane Surface(23) = {22}; Line Loop(24) = {16,17,14,15}; Plane Surface(25) = {24}; Line Loop(26) = {-17,20,1,5,-21,13}; Plane Surface(27) = {26}; -Line Loop(28) = {4,1,2,3}; Plane Surface(29) = {28}; -Line Loop(30) = {7,-2,5,6}; Plane Surface(31) = {30}; +Line Loop(28) = {-4,-1,-2,-3}; Plane Surface(29) = {28}; +Line Loop(30) = {-7,2,-5,-6}; Plane Surface(31) = {30}; Line Loop(32) = {6,-9,10,11,12,21}; Plane Surface(33) = {32}; Line Loop(34) = {7,3,8,9}; Plane Surface(35) = {34}; -Line Loop(36) = {10,-18,16,20,-4,8}; Plane Surface(37) = {36}; +Line Loop(36) = {-10,18,-16,-20,4,-8}; Plane Surface(37) = {36}; Line Loop(38) = {-14,-13,-12,19}; Plane Surface(39) = {38}; // Instead of using included files, let us now use a user-defined @@ -98,11 +98,11 @@ Function CheeseHole l1 = newreg; Line Loop(l1) = {c5,c10,c4}; Ruled Surface(newreg) = {l1}; l2 = newreg; Line Loop(l2) = {c9,-c5,c1}; Ruled Surface(newreg) = {l2}; - l3 = newreg; Line Loop(l3) = {-c12,c8,c1}; Ruled Surface(newreg) = {l3}; + l3 = newreg; Line Loop(l3) = {c12,-c8,-c1}; Ruled Surface(newreg) = {l3}; l4 = newreg; Line Loop(l4) = {c8,-c4,c11}; Ruled Surface(newreg) = {l4}; l5 = newreg; Line Loop(l5) = {-c10,c6,c3}; Ruled Surface(newreg) = {l5}; l6 = newreg; Line Loop(l6) = {-c11,-c3,c7}; Ruled Surface(newreg) = {l6}; - l7 = newreg; Line Loop(l7) = {c2,c7,c12}; Ruled Surface(newreg) = {l7}; + l7 = newreg; Line Loop(l7) = {-c2,-c7,-c12};Ruled Surface(newreg) = {l7}; l8 = newreg; Line Loop(l8) = {-c6,-c9,c2}; Ruled Surface(newreg) = {l8}; // Please note that all surface meshes are generated by projecting a -- GitLab