mirror of
https://github.com/NGSolve/netgen.git
synced 2025-01-01 08:40:34 +05:00
de7ffc5906
Current initialization of the global geometryregister suffers from a classic 'initialization order fiasco'. Depending on the order the compilation units are loaded/linked, the initialization of the global geometryregisterarray is not guaranteed to happen (and indeed often does not happen) before it is used. This leads to entries being appended before it's initialized (usually 'suceeding, but potentially causing memory corruption if the segment at that point isn't zeroed), initialization then happening halfway through (wiping the initial entries) and then the last entries being the only ones that show up. The net effect is either a crash at startup, or several geometry types seeming to be missing. Eg, step files will oad, but STL files are just ignored. The bug is actively observed on, eg, Linux. This patch implements a simple 'initialize at first access' convention for the array, eliminating the ordering problem. I've not reviewed the rest of the source for other potential examples of the fiasco pattern; this fixes only the geometryregister, since that was actively biting.
590 lines
15 KiB
C++
590 lines
15 KiB
C++
#include <mystdlib.h>
|
|
#include <myadt.hpp>
|
|
#include <linalg.hpp>
|
|
#include <csg.hpp>
|
|
|
|
#include <meshing.hpp>
|
|
|
|
|
|
#include <inctcl.hpp>
|
|
#include <visual.hpp>
|
|
|
|
#include <stlgeom.hpp>
|
|
|
|
#include "vsstl.hpp"
|
|
|
|
extern "C" int Ng_STL_Init (Tcl_Interp * interp);
|
|
|
|
|
|
|
|
namespace netgen
|
|
{
|
|
DLL_HEADER extern shared_ptr<NetgenGeometry> ng_geometry;
|
|
DLL_HEADER extern shared_ptr<Mesh> mesh;
|
|
DLL_HEADER extern MeshingParameters mparam;
|
|
DLL_HEADER extern STLParameters stlparam;
|
|
|
|
static VisualSceneSTLGeometry vsstlgeom;
|
|
static VisualSceneSTLMeshing vsstlmeshing;
|
|
|
|
char * err_needsstlgeometry = (char*) "This operation needs an STL geometry";
|
|
|
|
|
|
|
|
|
|
|
|
class STLGeometryVisRegister : public GeometryRegister
|
|
{
|
|
public:
|
|
virtual NetgenGeometry * Load (const filesystem::path & filename) const { return NULL; }
|
|
virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const;
|
|
virtual void SetParameters (Tcl_Interp * interp)
|
|
{
|
|
stlparam.yangle =
|
|
atof (Tcl_GetVar (interp, "::stloptions.yangle", 0));
|
|
stlparam.contyangle =
|
|
atof (Tcl_GetVar (interp, "::stloptions.contyangle", 0));
|
|
stlparam.edgecornerangle =
|
|
atof (Tcl_GetVar (interp, "::stloptions.edgecornerangle", 0));
|
|
stlparam.chartangle =
|
|
atof (Tcl_GetVar (interp, "::stloptions.chartangle", 0));
|
|
stlparam.outerchartangle =
|
|
atof (Tcl_GetVar (interp, "::stloptions.outerchartangle", 0));
|
|
|
|
stlparam.usesearchtree =
|
|
atoi (Tcl_GetVar (interp, "::stloptions.usesearchtree", 0));
|
|
|
|
|
|
stlparam.atlasminh =
|
|
atof (Tcl_GetVar (interp, "::stloptions.atlasminh", 0));
|
|
|
|
stlparam.resthsurfcurvfac =
|
|
atof (Tcl_GetVar (interp, "::stloptions.resthsurfcurvfac", 0));
|
|
stlparam.resthsurfcurvenable =
|
|
atoi (Tcl_GetVar (interp, "::stloptions.resthsurfcurvenable", 0));
|
|
|
|
stlparam.resthatlasfac =
|
|
atof (Tcl_GetVar (interp, "::stloptions.resthatlasfac", 0));
|
|
stlparam.resthatlasenable =
|
|
atoi (Tcl_GetVar (interp, "::stloptions.resthatlasenable", 0));
|
|
|
|
stlparam.resthchartdistfac =
|
|
atof (Tcl_GetVar (interp, "::stloptions.resthchartdistfac", 0));
|
|
stlparam.resthchartdistenable =
|
|
atoi (Tcl_GetVar (interp, "::stloptions.resthchartdistenable", 0));
|
|
|
|
stlparam.resthlinelengthfac =
|
|
atof (Tcl_GetVar (interp, "::stloptions.resthlinelengthfac", 0));
|
|
stlparam.resthlinelengthenable =
|
|
atoi (Tcl_GetVar (interp, "::stloptions.resthlinelengthenable", 0));
|
|
|
|
stlparam.resthedgeanglefac =
|
|
atof (Tcl_GetVar (interp, "::stloptions.resthedgeanglefac", 0));
|
|
stlparam.resthedgeangleenable =
|
|
atoi (Tcl_GetVar (interp, "::stloptions.resthedgeangleenable", 0));
|
|
|
|
stlparam.resthsurfmeshcurvfac =
|
|
atof (Tcl_GetVar (interp, "::stloptions.resthsurfmeshcurvfac", 0));
|
|
stlparam.resthsurfmeshcurvenable =
|
|
atoi (Tcl_GetVar (interp, "::stloptions.resthsurfmeshcurvenable", 0));
|
|
|
|
stlparam.recalc_h_opt =
|
|
atoi (Tcl_GetVar (interp, "::stloptions.recalchopt", 0));
|
|
// stlparam.Print (cout);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
int Ng_SetSTLParameters (ClientData clientData,
|
|
Tcl_Interp * interp,
|
|
int argc, tcl_const char *argv[])
|
|
{
|
|
STLGeometryVisRegister reg;
|
|
reg.SetParameters (interp);
|
|
|
|
return TCL_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int Ng_STLDoctor (ClientData clientData,
|
|
Tcl_Interp * interp,
|
|
int argc, tcl_const char *argv[])
|
|
{
|
|
//cout << "STL doctor" << endl;
|
|
STLGeometry * stlgeometry =
|
|
dynamic_cast<STLGeometry*> (ng_geometry.get());
|
|
|
|
|
|
stldoctor.drawmeshededges =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.drawmeshededges", 0));
|
|
|
|
stldoctor.geom_tol_fact =
|
|
atof (Tcl_GetVar (interp, "::stldoctor.geom_tol_fact", 0));
|
|
|
|
|
|
stldoctor.useexternaledges =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.useexternaledges", 0));
|
|
|
|
stldoctor.showfaces =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.showfaces", 0));
|
|
|
|
stldoctor.conecheck =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.conecheck", 0));
|
|
|
|
stldoctor.spiralcheck =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.spiralcheck", 0));
|
|
|
|
stldoctor.selectwithmouse =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.selectwithmouse", 0));
|
|
|
|
stldoctor.showedgecornerpoints =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.showedgecornerpoints", 0));
|
|
|
|
stldoctor.showmarkedtrigs =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.showmarkedtrigs", 0));
|
|
|
|
stldoctor.showtouchedtrigchart =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.showtouchedtrigchart", 0));
|
|
|
|
//cout << "smt=" << stldoctor.showmarkedtrigs << endl;
|
|
|
|
stldoctor.dirtytrigfact =
|
|
atof (Tcl_GetVar (interp, "::stldoctor.dirtytrigfact", 0));
|
|
|
|
stldoctor.smoothnormalsweight =
|
|
atof (Tcl_GetVar (interp, "::stldoctor.smoothnormalsweight", 0));
|
|
|
|
stldoctor.smoothangle =
|
|
atof (Tcl_GetVar (interp, "::stldoctor.smoothangle", 0));
|
|
|
|
stldoctor.selectmode =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.selectmode", 0));
|
|
|
|
stldoctor.edgeselectmode =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.edgeselectmode", 0));
|
|
|
|
stldoctor.longlinefact =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.longlinefact", 0));
|
|
|
|
stldoctor.showexcluded =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.showexcluded", 0));
|
|
|
|
|
|
|
|
if (!stldoctor.selectwithmouse)
|
|
{
|
|
stldoctor.selecttrig =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.selecttrig", 0));
|
|
|
|
stldoctor.nodeofseltrig =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.nodeofseltrig", 0));
|
|
}
|
|
|
|
stldoctor.showvicinity =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.showvicinity", 0));
|
|
|
|
stldoctor.vicinity =
|
|
atoi (Tcl_GetVar (interp, "::stldoctor.vicinity", 0));
|
|
|
|
|
|
if (argc >= 2)
|
|
{
|
|
if (!stlgeometry)
|
|
{
|
|
Tcl_SetResult (interp, err_needsstlgeometry, TCL_STATIC);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
if (strcmp (argv[1], "destroy0trigs") == 0)
|
|
{
|
|
stlgeometry->DestroyDirtyTrigs();
|
|
}
|
|
else if (strcmp (argv[1], "movepointtomiddle") == 0)
|
|
{
|
|
stlgeometry->MoveSelectedPointToMiddle();
|
|
}
|
|
else if (strcmp (argv[1], "calcnormals") == 0)
|
|
{
|
|
stlgeometry->CalcNormalsFromGeometry();
|
|
}
|
|
else if (strcmp (argv[1], "showchartnum") == 0)
|
|
{
|
|
stlgeometry->ShowSelectedTrigChartnum();
|
|
}
|
|
else if (strcmp (argv[1], "showcoords") == 0)
|
|
{
|
|
stlgeometry->ShowSelectedTrigCoords();
|
|
}
|
|
else if (strcmp (argv[1], "loadmarkedtrigs") == 0)
|
|
{
|
|
stlgeometry->LoadMarkedTrigs();
|
|
}
|
|
else if (strcmp (argv[1], "savemarkedtrigs") == 0)
|
|
{
|
|
stlgeometry->SaveMarkedTrigs();
|
|
}
|
|
else if (strcmp (argv[1], "neighbourangles") == 0)
|
|
{
|
|
stlgeometry->NeighbourAnglesOfSelectedTrig();
|
|
}
|
|
else if (strcmp (argv[1], "vicinity") == 0)
|
|
{
|
|
stlgeometry->CalcVicinity(stldoctor.selecttrig);
|
|
}
|
|
else if (strcmp (argv[1], "markdirtytrigs") == 0)
|
|
{
|
|
stlgeometry->MarkDirtyTrigs(stlparam);
|
|
}
|
|
else if (strcmp (argv[1], "smoothdirtytrigs") == 0)
|
|
{
|
|
stlgeometry->SmoothDirtyTrigs(stlparam);
|
|
}
|
|
else if (strcmp (argv[1], "smoothrevertedtrigs") == 0)
|
|
{
|
|
stlgeometry->GeomSmoothRevertedTrigs(stlparam);
|
|
}
|
|
else if (strcmp (argv[1], "invertselectedtrig") == 0)
|
|
{
|
|
stlgeometry->InvertTrig(stlgeometry->GetSelectTrig());
|
|
}
|
|
else if (strcmp (argv[1], "deleteselectedtrig") == 0)
|
|
{
|
|
stlgeometry->DeleteTrig(stlgeometry->GetSelectTrig());
|
|
}
|
|
else if (strcmp (argv[1], "smoothgeometry") == 0)
|
|
{
|
|
stlgeometry->SmoothGeometry();
|
|
}
|
|
else if (strcmp (argv[1], "orientafterselectedtrig") == 0)
|
|
{
|
|
stlgeometry->OrientAfterTrig(stlgeometry->GetSelectTrig());
|
|
}
|
|
else if (strcmp (argv[1], "marktoperrortrigs") == 0)
|
|
{
|
|
stlgeometry->MarkTopErrorTrigs();
|
|
}
|
|
else if (strcmp (argv[1], "exportedges") == 0)
|
|
{
|
|
stlgeometry->ExportEdges();
|
|
}
|
|
else if (strcmp (argv[1], "importedges") == 0)
|
|
{
|
|
stlgeometry->ImportEdges();
|
|
}
|
|
else if (strcmp (argv[1], "importexternaledges") == 0)
|
|
{
|
|
stlgeometry->ImportExternalEdges(argv[2]);
|
|
}
|
|
else if (strcmp (argv[1], "loadedgedata") == 0)
|
|
{
|
|
if (argc >= 3)
|
|
{
|
|
stlgeometry->LoadEdgeData(argv[2]);
|
|
}
|
|
}
|
|
else if (strcmp (argv[1], "saveedgedata") == 0)
|
|
{
|
|
if (argc >= 3)
|
|
{
|
|
stlgeometry->SaveEdgeData(argv[2]);
|
|
}
|
|
}
|
|
|
|
else if (strcmp (argv[1], "buildexternaledges") == 0)
|
|
{
|
|
stlgeometry->BuildExternalEdgesFromEdges();
|
|
}
|
|
else if (strcmp (argv[1], "smoothnormals") == 0)
|
|
{
|
|
stlgeometry->SmoothNormals(stlparam);
|
|
}
|
|
else if (strcmp (argv[1], "marknonsmoothnormals") == 0)
|
|
{
|
|
stlgeometry->MarkNonSmoothNormals(stlparam);
|
|
}
|
|
else if (strcmp (argv[1], "addexternaledge") == 0)
|
|
{
|
|
stlgeometry->AddExternalEdgeAtSelected();
|
|
}
|
|
else if (strcmp (argv[1], "addgeomline") == 0)
|
|
{
|
|
stlgeometry->AddExternalEdgesFromGeomLine();
|
|
}
|
|
else if (strcmp (argv[1], "addlonglines") == 0)
|
|
{
|
|
stlgeometry->AddLongLinesToExternalEdges();
|
|
}
|
|
else if (strcmp (argv[1], "addclosedlines") == 0)
|
|
{
|
|
stlgeometry->AddClosedLinesToExternalEdges();
|
|
}
|
|
else if (strcmp (argv[1], "addnotsinglelines") == 0)
|
|
{
|
|
stlgeometry->AddAllNotSingleLinesToExternalEdges();
|
|
}
|
|
else if (strcmp (argv[1], "deletedirtyexternaledges") == 0)
|
|
{
|
|
stlgeometry->DeleteDirtyExternalEdges();
|
|
}
|
|
else if (strcmp (argv[1], "deleteexternaledge") == 0)
|
|
{
|
|
stlgeometry->DeleteExternalEdgeAtSelected();
|
|
}
|
|
else if (strcmp (argv[1], "deletevicexternaledge") == 0)
|
|
{
|
|
stlgeometry->DeleteExternalEdgeInVicinity();
|
|
}
|
|
|
|
else if (strcmp (argv[1], "addlonglines") == 0)
|
|
{
|
|
stlgeometry->STLDoctorLongLinesToCandidates();
|
|
}
|
|
else if (strcmp (argv[1], "deletedirtyedges") == 0)
|
|
{
|
|
stlgeometry->STLDoctorDirtyEdgesToCandidates();
|
|
}
|
|
else if (strcmp (argv[1], "undoedgechange") == 0)
|
|
{
|
|
stlgeometry->UndoEdgeChange();
|
|
}
|
|
else if (strcmp (argv[1], "buildedges") == 0)
|
|
{
|
|
stlgeometry->STLDoctorBuildEdges(stlparam);
|
|
}
|
|
else if (strcmp (argv[1], "confirmedge") == 0)
|
|
{
|
|
stlgeometry->STLDoctorConfirmEdge();
|
|
}
|
|
else if (strcmp (argv[1], "candidateedge") == 0)
|
|
{
|
|
stlgeometry->STLDoctorCandidateEdge();
|
|
}
|
|
else if (strcmp (argv[1], "excludeedge") == 0)
|
|
{
|
|
stlgeometry->STLDoctorExcludeEdge();
|
|
}
|
|
else if (strcmp (argv[1], "undefinededge") == 0)
|
|
{
|
|
stlgeometry->STLDoctorUndefinedEdge();
|
|
}
|
|
else if (strcmp (argv[1], "setallundefinededges") == 0)
|
|
{
|
|
stlgeometry->STLDoctorSetAllUndefinedEdges();
|
|
}
|
|
else if (strcmp (argv[1], "erasecandidateedges") == 0)
|
|
{
|
|
stlgeometry->STLDoctorEraseCandidateEdges();
|
|
}
|
|
else if (strcmp (argv[1], "confirmcandidateedges") == 0)
|
|
{
|
|
stlgeometry->STLDoctorConfirmCandidateEdges();
|
|
}
|
|
else if (strcmp (argv[1], "confirmedtocandidateedges") == 0)
|
|
{
|
|
stlgeometry->STLDoctorConfirmedToCandidateEdges();
|
|
}
|
|
else if (strcmp (argv[1], "writechart") == 0)
|
|
{
|
|
int st = stlgeometry->GetSelectTrig();
|
|
|
|
if (st >= 1 && st <= stlgeometry->GetNT() && stlgeometry->AtlasMade())
|
|
{
|
|
auto chartnumber = stlgeometry->GetChartNr(st);
|
|
stlgeometry->WriteChartToFile(chartnumber, "chart.stlb");
|
|
}
|
|
}
|
|
}
|
|
|
|
return TCL_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int Ng_STLInfo (ClientData clientData,
|
|
Tcl_Interp * interp,
|
|
int argc, tcl_const char *argv[])
|
|
{
|
|
double data[10];
|
|
static char buf[20];
|
|
|
|
STLGeometry * stlgeometry = dynamic_cast<STLGeometry*> (ng_geometry.get());
|
|
|
|
if (!stlgeometry)
|
|
{
|
|
Tcl_SetResult (interp, err_needsstlgeometry, TCL_STATIC);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
|
|
|
|
if (stlgeometry)
|
|
{
|
|
stlgeometry->STLInfo(data);
|
|
// cout << "NT=" << data[0] << endl;
|
|
|
|
if (argc == 2)
|
|
{
|
|
if (strcmp (argv[1], "status") == 0)
|
|
{
|
|
switch (stlgeometry->GetStatus())
|
|
{
|
|
case STLGeometry::STL_GOOD:
|
|
strcpy (buf, "GOOD"); break;
|
|
case STLGeometry::STL_WARNING:
|
|
strcpy (buf, "WARNING"); break;
|
|
case STLGeometry::STL_ERROR:
|
|
strcpy (buf, "ERROR"); break;
|
|
}
|
|
Tcl_SetResult (interp, buf, TCL_STATIC);
|
|
return TCL_OK;
|
|
}
|
|
if (strcmp (argv[1], "statustext") == 0)
|
|
{
|
|
Tcl_SetResult (interp, (char*)stlgeometry->GetStatusText().c_str(), TCL_STATIC);
|
|
return TCL_OK;
|
|
}
|
|
if (strcmp (argv[1], "topology_ok") == 0)
|
|
{
|
|
sprintf (buf, "%d", stlgeometry->Topology_Ok());
|
|
Tcl_SetResult (interp, buf, TCL_STATIC);
|
|
}
|
|
if (strcmp (argv[1], "orientation_ok") == 0)
|
|
{
|
|
sprintf (buf, "%d", stlgeometry->Orientation_Ok());
|
|
Tcl_SetResult (interp, buf, TCL_STATIC);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data[0] = 0;
|
|
data[1] = 0;
|
|
data[2] = 0;
|
|
data[3] = 0;
|
|
data[4] = 0;
|
|
data[5] = 0;
|
|
data[6] = 0;
|
|
data[7] = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
sprintf (buf, "%i", (int)data[0]);
|
|
Tcl_SetVar (interp, argv[1], buf, 0);
|
|
|
|
sprintf (buf, "%5.3g", data[1]);
|
|
Tcl_SetVar (interp, argv[2], buf, 0);
|
|
sprintf (buf, "%5.3g", data[2]);
|
|
Tcl_SetVar (interp, argv[3], buf, 0);
|
|
sprintf (buf, "%5.3g", data[3]);
|
|
Tcl_SetVar (interp, argv[4], buf, 0);
|
|
|
|
sprintf (buf, "%5.3g", data[4]);
|
|
Tcl_SetVar (interp, argv[5], buf, 0);
|
|
sprintf (buf, "%5.3g", data[5]);
|
|
Tcl_SetVar (interp, argv[6], buf, 0);
|
|
sprintf (buf, "%5.3g", data[6]);
|
|
Tcl_SetVar (interp, argv[7], buf, 0);
|
|
|
|
sprintf (buf, "%i", (int)data[7]);
|
|
Tcl_SetVar (interp, argv[8], buf, 0);
|
|
|
|
return TCL_OK;
|
|
}
|
|
|
|
|
|
|
|
extern int Ng_SetMeshingParameters (ClientData clientData,
|
|
Tcl_Interp * interp,
|
|
int argc, tcl_const char *argv[]);
|
|
|
|
int Ng_STLCalcLocalH (ClientData clientData,
|
|
Tcl_Interp * interp,
|
|
int argc, tcl_const char *argv[])
|
|
{
|
|
GeometryRegisterArray& gra = FetchGeometryRegisterArray();
|
|
for (int i = 0; i < gra.Size(); i++)
|
|
gra[i]->SetParameters (interp);
|
|
|
|
|
|
Ng_SetMeshingParameters (clientData, interp, argc, argv);
|
|
|
|
STLGeometry * stlgeometry = dynamic_cast<STLGeometry*> (ng_geometry.get());
|
|
if (mesh && stlgeometry)
|
|
{
|
|
mesh -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10),
|
|
stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10),
|
|
mparam.grading);
|
|
stlgeometry -> RestrictLocalH(*mesh, mparam.maxh, stlparam, mparam);
|
|
|
|
if (stlparam.resthsurfmeshcurvenable)
|
|
mesh -> CalcLocalHFromSurfaceCurvature (mparam.grading,
|
|
stlparam.resthsurfmeshcurvfac);
|
|
}
|
|
|
|
return TCL_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
VisualScene * STLGeometryVisRegister :: GetVisualScene (const NetgenGeometry * geom) const
|
|
{
|
|
const STLGeometry * geometry = dynamic_cast<const STLGeometry*> (geom);
|
|
if (geometry)
|
|
{
|
|
vsstlmeshing.SetGeometry (const_cast<STLGeometry*> (geometry));
|
|
return &vsstlmeshing;
|
|
}
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
using namespace netgen;
|
|
|
|
extern "C" int Ng_stl_Init (Tcl_Interp * interp);
|
|
int Ng_stl_Init (Tcl_Interp * interp)
|
|
{
|
|
GeometryRegisterArray& gra = FetchGeometryRegisterArray();
|
|
gra.Append (new STLGeometryVisRegister);
|
|
|
|
Tcl_CreateCommand (interp, "Ng_SetSTLParameters", Ng_SetSTLParameters,
|
|
(ClientData)NULL,
|
|
(Tcl_CmdDeleteProc*) NULL);
|
|
|
|
Tcl_CreateCommand (interp, "Ng_STLDoctor", Ng_STLDoctor,
|
|
(ClientData)NULL,
|
|
(Tcl_CmdDeleteProc*) NULL);
|
|
|
|
Tcl_CreateCommand (interp, "Ng_STLInfo", Ng_STLInfo,
|
|
(ClientData)NULL,
|
|
(Tcl_CmdDeleteProc*) NULL);
|
|
|
|
Tcl_CreateCommand (interp, "Ng_STLCalcLocalH", Ng_STLCalcLocalH,
|
|
(ClientData)NULL,
|
|
(Tcl_CmdDeleteProc*) NULL);
|
|
|
|
|
|
return TCL_OK;
|
|
}
|