/*----------------------------------------------------------------------------- * * ID: m_func 02.11.06 0.0.A. * * Summary: The func, method, operator, property, text processing * -----------------------------------------------------------------------------*/ plexem STDCALL m_func( plexem curlex, uint flgextern ) { #ifdef DOUT uint i; #endif uint funckey; //Вид функции uint flgfunc; //Флаги функции pflabel curlabel; // Текущий элемент в таблице меток pflabel endlabel; // Конец таблицы меток uint isreturn; //Есть return uint thistype; //Тип переменной this для методов+ pubyte name; //Имя функции plexem lexname; //Лексема с именем функции plexem lexprev; s_desctype desctype;//Описание типа s_descid descvar; //Описание переменной uint off_parcount; //Смещение в заголовке функции на кол. параметров uint off_blccount; //Смещение в заголовке функции на кол. блоков bcflag bcf; //Переменная для получение флагов функции pbuf b; pfwith pwith; pvmobj funcobj; uint thisid; //Номер переменной для this в текст функции D( "Func start\n" ); // Инициализация desctype.idtype = 0; descvar.idtype = 0; descvar.flgdesc = 0; mem_zero( &fd, sizeof( fd ) ); thistype = 0; funckey = curlex->key; hash_init( &fd.nvars, sizeof( uint ) ); hash_init( &fd.nlabels, sizeof( uint ) ); for ( b = &fd.bhead; b <= &fd.bvarsas; b++ ) { buf_init( b ); buf_reserve( b, 0x200 ); b->step = 0x200; } fd.bvars.use = sizeof( fvar ); fd.blabels.use = sizeof( flabel ); // _compile->pout = &fd.bhead; // fd.blcount = 0; // fd.varcount = 0; // fd.curcount = 0; // fd.lastcurcount = 0; // fd.bllevel = 0; // fd.blcycle = 0; fd.offlcbreak = -1; fd.offlccontinue = -1; // fd.functype = 0; switch ( funckey ) { case KEY_METHOD: flgfunc = GHBC_METHOD; break; case KEY_OPERATOR: flgfunc = GHBC_OPERATOR; break; case KEY_PROPERTY: flgfunc = GHBC_PROPERTY; break; case KEY_TEXT: flgfunc = GHBC_TEXT; break; default: flgfunc = 0; } curlex = lexem_next( curlex, LEXNEXT_IGNLINE ); // Получаем тип возвращаемого значения функции/метода если он есть if ( curlex->type == LEXEM_NAME ) curlex = desc_idtype( curlex, &desctype ); if ( desctype.idtype ) { if ( ( funckey == KEY_METHOD || funckey == KEY_PROPERTY ) && curlex->type == LEXEM_OPER && curlex->oper.operid == OpWith ) { //Возврат на лексему влево текущая лексема тип объекта desctype.idtype = 0; curlex--; } else { fd.functype = desctype.idtype; fd.funcoftype = desctype.oftype; } } lexprev = curlex; curlex = lexem_next( curlex, LEXNEXT_SKIPLINE ); // Получаем тип объекта для метода if ( funckey == KEY_METHOD || funckey == KEY_PROPERTY ) { //Получаем тип объекта if ( curlex->type > 32 ) msg( MExptype | MSG_LEXERR, lexprev ); if ( thistype = bc_type( curlex ) ) { curlex = lexem_next( curlex, 0 ); if ( curlex->type == LEXEM_OPER && curlex->oper.operid == OpWith ) { curlex = lexem_next( curlex, 0 ); } else msg( MExppoint | MSG_LEXERR, curlex ); } else msg( MExptype | MSG_LEXERR, curlex ); } // Получение имени функции, метода ... if ( funckey == KEY_OPERATOR ) { if ( curlex->type != LEXEM_OPER ) msg( MExpoper | MSG_LEXERR, curlex ); name = ( pubyte )&curlex->oper.name; } else { if ( curlex->type != LEXEM_NAME ) msg( MExpname | MSG_LEXERR, curlex ); name = lexem_getname( curlex ); } lexname = curlex; _vm.pos = curlex->pos; // Получение списка директив curlex = lexem_next( curlex, flgextern ? 0 : LEXNEXT_IGNLINE ); curlex = bc_flag( curlex, BFLAG_FUNC, &bcf ); flgfunc |= GHCOM_NAME | bcf.value; _compile->pout = &fd.bhead; out_head( OVM_BYTECODE, flgfunc, name ); create_varmode( &fd.bhead, &desctype, 0 );//Возвращаемое значение off_parcount = fd.bhead.use; out_adduint( 0 );//Количество параметров if ( funckey == KEY_METHOD || funckey == KEY_PROPERTY ) { //Создание параметра this mem_zero( &descvar, sizeof( descvar )); descvar.idtype = thistype; descvar.name = "this"; descvar.lex = curlex; descvar.flgdesc = DESCID_PARFUNC; pwith = ( pfwith )buf_appendtype( &fd.bwith, sizeof( fwith )) ; pwith->num = var_checkadd( &descvar ); pwith->oftype = 0; pwith->type = thistype; } //Получение списка параметров if ( curlex->type == LEXEM_OPER && curlex->oper.operid == OpLbrack )//Открывающая скобка { curlex = lexem_next( curlex, LEXNEXT_IGNLINE ); curlex = var_def( curlex, DESCID_PARFUNC ); if ( curlex->type != LEXEM_OPER ||//Системная лексема curlex->oper.operid != OpRbrack )//Закрывающая скобка msg( MExpclosebr | MSG_LEXERR, curlex ); curlex = lexem_next( curlex, flgextern ? 0 : LEXNEXT_IGNLINE ); } else { if ( funckey == KEY_OPERATOR ) msg( MExpopenbr | MSG_LEXERR, curlex ); } fd.flgfunc = flgfunc; if ( flgfunc & GHBC_RESULT ) { //Создание параметра result if ( !fd.functype || fd.functype <= TUlong ) msg( MResulttype | MSG_LEXERR, curlex ); mem_zero( &descvar, sizeof( descvar )); descvar.idtype = desctype.idtype; descvar.oftype = desctype.oftype; descvar.flgdesc = DESCID_PARFUNC; descvar.name = "result"; descvar.lex = curlex; fd.idresult = var_checkadd( &descvar ); fd.functype = 0; } if ( fd.varcount ) { *( puint )( fd.bhead.data + off_parcount ) = fd.varcount;//Кол-во параметров if ( flgfunc & ( GHBC_ENTRY | GHBC_MAIN ) ) msg( MMainpar | MSG_LEXERR, curlex ); fd.curcount = 0; } off_blccount = fd.bhead.use; out_adduint( 0 );//Количество блоков if ( funckey == KEY_PROPERTY ) { if ( ( fd.functype && fd.varcount > 1 ) || (!fd.functype && fd.varcount != 2 )) { msg( MProppar | MSG_LEXERR, curlex );//Неверное количество параметров в описании свойства } if ( type_fieldname( thistype, name ) ) { msg( MPropfield | MSG_LEXERR, curlex );//Свойство совпадает с именем поля } } funcobj = load_bytecode( &fd.bhead.data, flgextern ? VMLOAD_EXTERN : VMLOAD_FIRST ); if ( bcf.value & GHRT_ALIAS ) { alias_setid( bcf.alias, funcobj->id ); } if ( !( flgextern ) ) { if ( _compile->flag & CMPL_DEBUG ) { _compile->pout = fd.bout = &fd.bsubout; out_adduints( 3, CDatasize, str_len( _compile->cur->filename ) + 5, str_pos2line( _compile->cur->src, lexname->pos, 0 ) + 1 ); out_addptr( str_ptr( _compile->cur->filename ), str_len( _compile->cur->filename ) + 1 ); out_adduint( CDbgFunc ); _compile->pout = fd.bout = &fd.bfuncout; } _compile->pout = fd.bout = &fd.bfuncout; if ( funckey == KEY_TEXT ) { //Создание параметра this для Text функции mem_zero( &descvar, sizeof( descvar )); descvar.idtype = TUint; descvar.name = "this"; descvar.lex = curlex; descvar.flgdesc = DESCID_VAR;///DESCID_PARFUNC; thisid = var_checkadd( &descvar ); /*pwith = ( pfwith )buf_appendtype( &fd.bwith, sizeof( fwith )) ; pwith->num = var_checkadd( &descvar ); //print( "ssssssssss %x %x %x %x", fd.bvars.data, fd.bvars.use, pwith->num, sizeof( fvar ) ); pwith->oftype = 0; pwith->type = TStr;*/ ((pfvar)(fd.bvars.data + fd.bvars.use - sizeof( fvar )))->type = TStr; out_adduints( 4, CVarptrload, thisid, CGetText, CSetI ); /*buf_appenduint( &fd.bblinit, CVarptrload ); buf_appenduint( &fd.bblinit, thisid ); buf_appenduint( &fd.bblinit, CGetText ); buf_appenduint( &fd.bblinit, CSetI );*/ } curlex = f_body( curlex ); *((puint)(fd.bhead.data+off_blccount)) = fd.blcount; curlabel = ( pflabel )( fd.blabels.data ) + 1; endlabel = ( pflabel )( fd.blabels.data + fd.blabels.use ); //Контроль неразрешённых меток и проверка выходов из функции isreturn = 0; while( curlabel < endlabel ) { if ( curlabel->type & LABT_GT ) { if ( ( curlabel->type & LABT_GTUNDEF ) == LABT_GTUNDEF ) msg( MUnklabel | MSG_LEXNAMEERR, curlabel->lex ); *( puint )(fd.bfuncout.data + curlabel->offbout ) = ((( pflabel )(fd.blabels.data + curlabel->link ))->offbout + fd.bsubout.use )/sizeof(uint); if ( !isreturn )//Помечаем метку как отработавшую (на неё был переход) (( pflabel )(fd.blabels.data + curlabel->link ))->type |= LABT_LABELWORK; } else if ( curlabel->type & LABT_RETURN ) { isreturn = 1;//Устанавливаем флаг } else if ( curlabel->type & LABT_LABELWORK ) isreturn = 0;//Если была отработавшая метка, то сбрасываем флаг curlabel++; } if ( fd.functype ) { if ( !isreturn ) msg( MMustret | MSG_LEXNAMEERR, lexname ); } else if ( !isreturn ) { if ( fd.flgfunc & GHBC_RESULT ) { out_add2uint( CVarload, fd.idresult ); } out_adduint( CReturn ); } buf_add( &fd.bhead, &fd.bvardef ); if ( fd.bsubout.use ) { if ( fd.offsubgoto ) { //*((( puint)fd.bsubout.data ) + 1) = fd.bsubout.use/sizeof( uint ); *( puint )( fd.bsubout.data + fd.offsubgoto ) = fd.bsubout.use / sizeof( uint ); } buf_add( &fd.bhead, &fd.bsubout ); } buf_add( &fd.bhead, &fd.bfuncout ); _compile->pout = &fd.bhead; out_finish(); #ifdef DOUT //Тестируемый вывод //if ( name[0] == 'c' && name[1] == 'r' ) getch(); print( "FUNC OUT %x %s:\n", funcobj->id, name ); for (i = 0; i < fd.bhead.use ; i++ ) { print( " %x", fd.bhead.data[i] ); } print( "\n" ); #endif load_bytecode( &fd.bhead.data, VMLOAD_OK ); // print( "funcobjid2 =%x\n", funcobj->id ); } //Очистка памяти for ( b = &fd.bhead;/*&fd.bblinit;*/ b <= &fd.bvarsas; b++ ) { buf_delete( b ); } hash_delete( &fd.nvars ); hash_delete( &fd.nlabels ); D( "Func Stop\n" ); return curlex; }
int main (int argc, char* argv[]) { ApplicationsLib::LogogSetup logog_setup; TCLAP::CmdLine cmd( "Creates boundary conditions for mesh nodes along polylines." "The documentation is available at https://docs.opengeosys.org/docs/tools/model-preparation/create-boundary-conditions-along-a-polyline", ' ', "0.1"); TCLAP::ValueArg<bool> gml_arg("", "gml", "if switched on write found nodes to file in gml format", false, 0, "bool"); cmd.add(gml_arg); TCLAP::ValueArg<std::string> output_base_fname("o", "output-base-file-name", "the base name of the file the output (geometry (gli) and boundary"\ "condition (bc)) will be written to", true, "", "file name"); cmd.add(output_base_fname); TCLAP::ValueArg<std::string> bc_type("t", "type", "the process type the boundary condition will be written for "\ "currently LIQUID_FLOW (primary variable PRESSURE1) and "\ "GROUNDWATER_FLOW (primary variable HEAD, default) are supported", true, "", "process type as string (LIQUID_FLOW or GROUNDWATER_FLOW (default))"); cmd.add(bc_type); TCLAP::ValueArg<double> search_length_arg("s", "search-length", "The size of the search length. The default value is " "std::numeric_limits<double>::epsilon()", false, std::numeric_limits<double>::epsilon(), "floating point number"); cmd.add(search_length_arg); TCLAP::ValueArg<std::string> geometry_fname("i", "input-geometry", "the name of the file containing the input geometry", true, "", "file name"); cmd.add(geometry_fname); TCLAP::ValueArg<std::string> mesh_arg("m", "mesh-file", "the name of the file containing the mesh", true, "", "file name"); cmd.add(mesh_arg); cmd.parse(argc, argv); // *** read mesh INFO("Reading mesh \"%s\" ... ", mesh_arg.getValue().c_str()); MeshLib::Mesh * subsurface_mesh(FileIO::readMeshFromFile(mesh_arg.getValue())); INFO("done."); INFO("Extracting top surface of mesh \"%s\" ... ", mesh_arg.getValue().c_str()); const MathLib::Vector3 dir(0,0,-1); double const angle(90); std::unique_ptr<MeshLib::Mesh> surface_mesh( MeshLib::MeshSurfaceExtraction::getMeshSurface(*subsurface_mesh, dir, angle)); INFO("done."); delete subsurface_mesh; subsurface_mesh = nullptr; // *** read geometry GeoLib::GEOObjects geometries; FileIO::readGeometryFromFile(geometry_fname.getValue(), geometries); std::string geo_name; { std::vector<std::string> geo_names; geometries.getGeometryNames(geo_names); geo_name = geo_names[0]; } // *** check if the data is usable // *** get vector of polylines std::vector<GeoLib::Polyline*> const* plys(geometries.getPolylineVec(geo_name)); if (!plys) { ERR("Could not get vector of polylines out of geometry \"%s\".", geo_name.c_str()); return -1; } MeshGeoToolsLib::SearchLength search_length_strategy; if (search_length_arg.isSet()) { search_length_strategy = MeshGeoToolsLib::SearchLength(search_length_arg.getValue()); } GeoLib::GEOObjects geometry_sets; MeshGeoToolsLib::MeshNodeSearcher mesh_searcher(*surface_mesh, search_length_strategy); for(std::size_t k(0); k<plys->size(); k++) { std::vector<std::size_t> ids (mesh_searcher.getMeshNodeIDsAlongPolyline(*((*plys)[k]))); if (ids.empty()) continue; std::string geo_name("Polyline-"+std::to_string(k)); convertMeshNodesToGeometry(surface_mesh->getNodes(), ids, geo_name, geometry_sets); } // merge all together std::vector<std::string> geo_names; geometry_sets.getGeometryNames(geo_names); if (geo_names.empty()) { ERR("Did not find mesh nodes along polylines."); return -1; } std::string merge_name("AllMeshNodesAlongPolylines"); if (geometry_sets.mergeGeometries(geo_names, merge_name) == 2) merge_name = geo_names[0]; GeoLib::PointVec const* pnt_vec(geometry_sets.getPointVecObj(merge_name)); std::vector<GeoLib::Point*> const* merged_pnts(pnt_vec->getVector()); std::vector<GeoLib::Point> pnts_with_id; const std::size_t n_merged_pnts(merged_pnts->size()); for(std::size_t k(0); k<n_merged_pnts; ++k) { pnts_with_id.emplace_back(*((*merged_pnts)[k]), k); } std::sort(pnts_with_id.begin(), pnts_with_id.end(), [](GeoLib::Point const& p0, GeoLib::Point const& p1) { return p0 < p1; } ); double const eps (std::numeric_limits<double>::epsilon()); auto surface_pnts = std::unique_ptr<std::vector<GeoLib::Point*>>( new std::vector<GeoLib::Point*>); std::map<std::string, std::size_t> *name_id_map( new std::map<std::string, std::size_t> ); // insert first point surface_pnts->push_back( new GeoLib::Point(pnts_with_id[0], surface_pnts->size())); std::string element_name; pnt_vec->getNameOfElementByID(0, element_name); name_id_map->insert( std::pair<std::string, std::size_t>(element_name,0) ); for (std::size_t k(1); k < n_merged_pnts; ++k) { const GeoLib::Point& p0 (pnts_with_id[k-1]); const GeoLib::Point& p1 (pnts_with_id[k]); if (std::abs (p0[0] - p1[0]) > eps || std::abs (p0[1] - p1[1]) > eps) { surface_pnts->push_back(new GeoLib::Point(pnts_with_id[k], surface_pnts->size())); std::string element_name; pnt_vec->getNameOfElementByID(k, element_name); name_id_map->insert( std::pair<std::string, std::size_t>(element_name, surface_pnts->size()-1) ); } } std::string surface_name(BaseLib::dropFileExtension(mesh_arg.getValue())+"-MeshNodesAlongPolylines"); geometry_sets.addPointVec(std::move(surface_pnts), surface_name, name_id_map, 1e-6); // write the BCs and the merged geometry set to file std::string const base_fname( BaseLib::dropFileExtension(output_base_fname.getValue())); writeBCsAndGeometry(geometry_sets, surface_name, base_fname, bc_type.getValue(), gml_arg.getValue()); return 0; }