Exemple #1
0
/*-----------------------------------------------------------------------------
*
* 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;
}