예제 #1
0
//---------------------------------------------------------
CSG_String CSG_Module_Library::Get_Summary(bool bHTML)
{
	CSG_String	s;

	if( bHTML )
	{
		s.Printf(
			SG_T("%s: <b>%s</b><br>%s: <i>%s</i><br>%s: <i>%s</i><br>%s: <i>%s</i><hr>%s"),
			LNG("[CAP] Module Library")	, Get_Info(MLB_INFO_Name),
			LNG("[CAP] Author")			, Get_Info(MLB_INFO_Author),
			LNG("[CAP] Version")		, Get_Info(MLB_INFO_Version),
			LNG("[CAP] File")			, Get_File_Name().c_str(),
			Get_Info(MLB_INFO_Description)
		);

		s.Append(CSG_String::Format(SG_T("<hr><b>%s:<ul>"), LNG("[CAP] Modules")));

		for(int i=0; i<Get_Count(); i++)
		{
			s.Append(CSG_String::Format(SG_T("<li>%s</li>"), Get_Module(i)->Get_Name()));
		}

		s.Append(SG_T("</ul>"));

		s.Replace(SG_T("\n"), SG_T("<br>"));
	}
	else
	{
		s.Printf(
			SG_T("%s: %s\n%s: %s\n%s: %s\n%s: %s\n\n%s"),
			LNG("[CAP] Module Library")	, Get_Info(MLB_INFO_Name),
			LNG("[CAP] Author")			, Get_Info(MLB_INFO_Author),
			LNG("[CAP] Version")		, Get_Info(MLB_INFO_Version),
			LNG("[CAP] File")			, Get_File_Name().c_str(),
			Get_Info(MLB_INFO_Description)
		);

		s.Append(CSG_String::Format(SG_T("\n\n%s:\n"), LNG("[CAP] Modules")));

		for(int i=0; i<Get_Count(); i++)
		{
			s.Append(CSG_String::Format(SG_T("- %s\n"), Get_Module(i)->Get_Name()));
		}
	}

	return( s );
}
예제 #2
0
//---------------------------------------------------------
CSG_String		SG_Get_String(double Value, int Precision, bool bScientific)
{
	CSG_String	s;

	if( Precision >= 0 )
	{
		s.Printf(SG_T("%.*f"), Precision, Value);
	}
	else if( Precision == -1 )
	{
		s.Printf(SG_T("%f"), Value);
	}
	else // if( Precision == -2 )
	{
		Precision	= SG_Get_Significant_Decimals(Value, abs(Precision));

		s.Printf(SG_T("%.*f"), SG_Get_Significant_Decimals(Value, abs(Precision)), Value);

		if( Precision > 0 )
		{
			while( s.Length() > 1 && s[s.Length() - 1] == '0' )
			{
				s	= s.Left(s.Length() - 1);
			}

			if( s.Length() > 1 && (s[s.Length() - 1] == '.' || s[s.Length() - 1] == ',') )
			{
				s	= s.Left(s.Length() - 1);
			}
		}
	}

	s.Replace(",", ".");

	return( s );
}
예제 #3
0
//---------------------------------------------------------
bool CGDAL_Formats::On_Execute(void)
{
    CSG_Table	*pFormats	= Parameters("FORMATS")->asTable();

    pFormats->Destroy();
    pFormats->Set_Name(_TL("GDAL Formats"));

    pFormats->Add_Field("ID"    , SG_DATATYPE_String);
    pFormats->Add_Field("NAME"  , SG_DATATYPE_String);
    pFormats->Add_Field("FILTER", SG_DATATYPE_String);
    pFormats->Add_Field("TYPE"  , SG_DATATYPE_String);
    pFormats->Add_Field("ACCESS", SG_DATATYPE_String);

    //-----------------------------------------------------
    int		Type	= Parameters("TYPE"  )->asInt();
    int		Access	= Parameters("ACCESS")->asInt();

    //-----------------------------------------------------
    if( Type != 1 )	// not vectors only
    {
        for(int i=0; i<SG_Get_GDAL_Drivers().Get_Count(); i++)
        {
            if( SG_Get_GDAL_Drivers().is_Raster(i) )
            {
                CSG_String	R(SG_Get_GDAL_Drivers().Can_Read (i) ? "R" : "");
                CSG_String	W(SG_Get_GDAL_Drivers().Can_Write(i) ? "W" : "");

                if( (Access != 0 || !R.is_Empty()) && (Access != 1 || !W.is_Empty()) )
                {
                    CSG_Table_Record	*pFormat	= pFormats->Add_Record();

                    pFormat->Set_Value(GDAL_LIST_FMT_ID    , SG_Get_GDAL_Drivers().Get_Description(i));
                    pFormat->Set_Value(GDAL_LIST_FMT_NAME  , SG_Get_GDAL_Drivers().Get_Name       (i));
                    pFormat->Set_Value(GDAL_LIST_FMT_FILTER, SG_Get_GDAL_Drivers().Get_Extension  (i));
                    pFormat->Set_Value(GDAL_LIST_FMT_TYPE  , "RASTER");
                    pFormat->Set_Value(GDAL_LIST_FMT_ACCESS, R + W);
                }
            }
        }
    }

    //-----------------------------------------------------
    if( Type != 0 )	// not rasters only
    {
        for(int i=0; i<SG_Get_OGR_Drivers().Get_Count(); i++)
        {
            if( SG_Get_OGR_Drivers().is_Vector(i) )
            {
                CSG_String	R(SG_Get_OGR_Drivers().Can_Read (i) ? "R" : "");
                CSG_String	W(SG_Get_OGR_Drivers().Can_Write(i) ? "W" : "");

                if( (Access != 0 || !R.is_Empty()) && (Access != 1 || !W.is_Empty()) )
                {
                    CSG_Table_Record	*pFormat	= pFormats->Add_Record();

                    pFormat->Set_Value(GDAL_LIST_FMT_ID    , SG_Get_OGR_Drivers().Get_Description(i));
                    pFormat->Set_Value(GDAL_LIST_FMT_NAME  , SG_Get_OGR_Drivers().Get_Name       (i));
                    pFormat->Set_Value(GDAL_LIST_FMT_FILTER, SG_Get_OGR_Drivers().Get_Extension  (i));
                    pFormat->Set_Value(GDAL_LIST_FMT_TYPE  , "VECTOR");
                    pFormat->Set_Value(GDAL_LIST_FMT_ACCESS, R + W);
                }
            }
        }
    }

    //-----------------------------------------------------
    if( Parameters("RECOGNIZED")->asBool() )
    {
        CSG_String	Filter_All;

        for(int i=0; i<pFormats->Get_Count(); i++)
        {
            CSG_String	Filter	= pFormats->Get_Record(i)->asString(GDAL_LIST_FMT_FILTER);

            if( !Filter.is_Empty() )
            {
                Filter.Replace("/", ";");

                Filter_All	+= (Filter_All.is_Empty() ? "*." : ";*.") + Filter;
            }
        }

        if( !Filter_All.is_Empty() )
        {
            CSG_Table_Record	*pFormat	= pFormats->Add_Record();

            pFormat->Set_Value(GDAL_LIST_FMT_NAME  , _TL("All Recognized Files"));
            pFormat->Set_Value(GDAL_LIST_FMT_FILTER, Filter_All);
            pFormat->Set_Value(GDAL_LIST_FMT_TYPE  , Type   == 0 ? "RASTER" : Type   == 1 ? "VECTOR" : "RASTER/VECTOR");
            pFormat->Set_Value(GDAL_LIST_FMT_ACCESS, Access == 0 ? "R"      : Access == 1 ? "W"      : "RW"           );
        }
    }

    //-----------------------------------------------------
    return( pFormats->Get_Count() > 0 );
}
//---------------------------------------------------------
CSG_Grid * CLandsat_Import::Get_Band(const CSG_String &File)
{
	CSG_Data_Manager	tmpMgr;

	if( !tmpMgr.Add(File) || !tmpMgr.Get_Grid_System(0) || !tmpMgr.Get_Grid_System(0)->Get(0) )
	{
		Error_Set(CSG_String::Format(SG_T("%s: %s"), _TL("could not load file"), File.c_str()));

		return( NULL );
	}

	tmpMgr.Get_Grid_System(0)->Get(0)->Set_NoData_Value(0);	// landsat 8 pretends to use a value of 65535 (2^16 - 1)

	CSG_Grid	*pBand	= NULL;

	//-----------------------------------------------------
	if( !tmpMgr.Get_Grid_System(0)->Get(0)->Get_Projection().is_Okay() )
	{
		// undefined coordinate system, nothing to do be done further...
	}

	//-----------------------------------------------------
	else if( Parameters("PROJECTION")->asInt() == 2 )	// Geographic Coordinates
	{
		pBand	= Get_Projection((CSG_Grid *)tmpMgr.Get_Grid_System(0)->Get(0), "+proj=longlat +ellps=WGS84 +datum=WGS84");
	}

	//-----------------------------------------------------
	else												// UTM
	{
		CSG_Grid	*pTmp	= (CSG_Grid *)tmpMgr.Get_Grid_System(0)->Get(0);

		CSG_String	Projection	= pTmp->Get_Projection().Get_Proj4();

		if( Projection.Find("+proj=utm") >= 0
		&&  (  (Projection.Find("+south") >= 0 && Parameters("PROJECTION")->asInt() == 0)
		    || (Projection.Find("+south") <  0 && Parameters("PROJECTION")->asInt() == 1))
		&&  (pBand = SG_Create_Grid(pTmp->Get_Type(), pTmp->Get_NX(), pTmp->Get_NY(), pTmp->Get_Cellsize(),
				pTmp->Get_XMin(), pTmp->Get_YMin() + (Parameters("PROJECTION")->asInt() == 1 ? 10000000 : -10000000)
			)) != NULL )
		{
			if( Parameters("PROJECTION")->asInt() == 1 )
				Projection.Append (" +south");
			else
				Projection.Replace(" +south", "");

			pBand->Get_Projection().Create(Projection, SG_PROJ_FMT_Proj4);

			pBand->Set_Name              (pTmp->Get_Name());
			pBand->Set_Description       (pTmp->Get_Description());
			pBand->Set_NoData_Value_Range(pTmp->Get_NoData_Value(), pTmp->Get_NoData_hiValue());
			pBand->Set_Scaling           (pTmp->Get_Scaling(), pTmp->Get_Offset());

			#pragma omp parallel for
			for(int y=0; y<pBand->Get_NY(); y++)
			{
				for(int x=0; x<pBand->Get_NX(); x++)
				{
					pBand->Set_Value(x, y, pTmp->asDouble(x, y));
				}
			}
		}
	}

	//-----------------------------------------------------
	if( !pBand )
	{
		pBand	= (CSG_Grid *)tmpMgr.Get_Grid_System(0)->Get(0);

		tmpMgr.Delete(tmpMgr.Get_Grid_System(0)->Get(0), true);	// make permanent, detach from temporary data manager
	}

	return( pBand );
}
예제 #5
0
//---------------------------------------------------------
bool CPGIS_Shapes_Save::On_Execute(void)
{
	int			SRID;
	CSG_Shapes	*pShapes;
	CSG_String	SQL, Geo_Table, Geo_Type, Geo_Field, sSRID;

	pShapes		= Parameters("SHAPES")	->asShapes();
	Geo_Table	= Parameters("NAME")	->asString();	if( Geo_Table.Length() == 0 )	Geo_Table	= pShapes->Get_Name();
	SRID		= Parameters("SRID")	->asInt();
	SRID		= SG_Get_Projections().Get_SRID_byNamesIndex(SRID);

	sSRID.Printf(SG_T("%d"), SRID);

	//-----------------------------------------------------
	switch( pShapes->Get_Vertex_Type() )
	{
	case SG_VERTEX_TYPE_XY:
		switch( pShapes->Get_Type() )
		{	default:	return( false );
		case SHAPE_TYPE_Point:		Geo_Type	= SG_OGIS_TYPE_STR_Point;			Geo_Field	= SG_T("geo_point");		break;
		case SHAPE_TYPE_Points:		Geo_Type	= SG_OGIS_TYPE_STR_MultiPoint;		Geo_Field	= SG_T("geo_points");		break;
		case SHAPE_TYPE_Line:		Geo_Type	= SG_OGIS_TYPE_STR_MultiLine;		Geo_Field	= SG_T("geo_line");			break;
		case SHAPE_TYPE_Polygon:	Geo_Type	= SG_OGIS_TYPE_STR_MultiPolygon;	Geo_Field	= SG_T("geo_polygon");		break;
		}
		break;

	case SG_VERTEX_TYPE_XYZ:
		switch( pShapes->Get_Type() )
		{	default:	return( false );
		case SHAPE_TYPE_Point:		Geo_Type	= SG_OGIS_TYPE_STR_Point_Z;			Geo_Field	= SG_T("geo_point_z");		break;
		case SHAPE_TYPE_Points:		Geo_Type	= SG_OGIS_TYPE_STR_MultiPoint_Z;	Geo_Field	= SG_T("geo_points_z");		break;
		case SHAPE_TYPE_Line:		Geo_Type	= SG_OGIS_TYPE_STR_MultiLine_Z;		Geo_Field	= SG_T("geo_line_z");		break;
		case SHAPE_TYPE_Polygon:	Geo_Type	= SG_OGIS_TYPE_STR_MultiPolygon_Z;	Geo_Field	= SG_T("geo_polygon_z");	break;
		}
		break;

	case SG_VERTEX_TYPE_XYZM:
		switch( pShapes->Get_Type() )
		{	default:	return( false );
		case SHAPE_TYPE_Point:		Geo_Type	= SG_OGIS_TYPE_STR_Point_ZM;		Geo_Field	= SG_T("geo_point_zm");		break;
		case SHAPE_TYPE_Points:		Geo_Type	= SG_OGIS_TYPE_STR_MultiPoint_ZM;	Geo_Field	= SG_T("geo_points_zm");	break;
		case SHAPE_TYPE_Line:		Geo_Type	= SG_OGIS_TYPE_STR_MultiLine_ZM;	Geo_Field	= SG_T("geo_line_zm");		break;
		case SHAPE_TYPE_Polygon:	Geo_Type	= SG_OGIS_TYPE_STR_MultiPolygon_ZM;	Geo_Field	= SG_T("geo_polygon_zm");	break;
		}
		break;
	}

	//-----------------------------------------------------
	if( Get_Connection()->Table_Exists(Geo_Table) )
	{
		Message_Add(CSG_String::Format(SG_T("%s: %s"), _TL("table already exists"), Geo_Table.c_str()));

		switch( Parameters("EXISTS")->asInt() )
		{
		case 0:	// abort export
			return( false );

		case 1:	// replace existing table
			Message_Add(CSG_String::Format(SG_T("%s: %s"), _TL("trying to drop table"), Geo_Table.c_str()));

			if( !Get_Connection()->Table_Drop(Geo_Table, false) )
			{
				Message_Add(CSG_String::Format(SG_T(" ...%s!"), _TL("failed")));

				return( false );
			}

			break;

		case 2:	// append records, if table structure allows
			break;
		}
	}

	//-----------------------------------------------------
	if( !Get_Connection()->Table_Exists(Geo_Table) && !Get_Connection()->Table_Create(Geo_Table, *pShapes, Get_Constraints(Parameters("FLAGS")->asParameters(), pShapes), false) )
	{
		Get_Connection()->Rollback();

		return( false );
	}

	//-----------------------------------------------------
	SQL.Printf(SG_T("SELECT AddGeometryColumn('%s', '%s', %d, '%s', %d)"),
		Geo_Table.c_str(),				// <table_name>
		Geo_Field.c_str(),				// <column_name>
		SRID,							// <srid>
		Geo_Type.Make_Upper().c_str(),	// <type>
		2								// <dimension>
	);

	if( !Get_Connection()->Execute(SQL) )
	{
		Get_Connection()->Rollback();

		Message_Add(_TL("could not create geometry field"));

		return( false );
	}

	//-----------------------------------------------------
	int			iShape, iField, nAdded;
	CSG_String	Insert, Fields, sWKT;

	Fields	= Geo_Field;

	for(iField=0; iField<pShapes->Get_Field_Count(); iField++)
	{
		Fields	+= CSG_String(", ") + pShapes->Get_Field_Name(iField);
	}

	Insert.Printf(SG_T("INSERT INTO %s (%s) VALUES ("), Geo_Table.c_str(), Fields.c_str());

	for(iShape=0, nAdded=0; iShape<pShapes->Get_Count() && Set_Progress(iShape, pShapes->Get_Count()); iShape++)
	{
		CSG_Shape	*pShape	= pShapes->Get_Shape(iShape);

		if( pShape->is_Valid() )
		{
			SQL	= Insert;

			CSG_Shapes_OGIS_Converter::to_WKText(pShape, sWKT);

			SQL	+= SG_T("GeomFromText('") + sWKT + SG_T("', ") + sSRID + SG_T(")");

			for(iField=0; iField<pShapes->Get_Field_Count(); iField++)
			{
				CSG_String	s = pShape->asString(iField);

				if( pShapes->Get_Field_Type(iField) == SG_DATATYPE_String )
				{
					s.Replace(SG_T("'"), SG_T("\""));
					s	= SG_T("'") + s + SG_T("'");
				}

				SQL	+= SG_T(", ")  + s;
			}

			SQL	+= SG_T(")");

			if( Get_Connection()->Execute(SQL) )
			{
				nAdded++;
			}
			else
			{
				Message_Add(CSG_String::Format(SG_T("dropped %d. shape"), iShape));
			}
		}
	}

	//-----------------------------------------------------
	if( nAdded == 0 )
	{
		Get_Connection()->Rollback();

		Get_Connection()->Table_Drop(Geo_Table);

		return( false );
	}

	return( Get_Connection()->Commit() );
}
예제 #6
0
//---------------------------------------------------------
bool CShapes_Save::On_Execute(void)
{
	if( !Get_Connection()->has_PostGIS() )
	{
		Error_Set(_TL("not a valid PostGIS database!"));

		return( false );
	}

	//-----------------------------------------------------
	CSG_Shapes	*pShapes;
	CSG_String	SQL, Name, Type, Field, SavePoint;

	pShapes		= Parameters("SHAPES")->asShapes();
	Name		= Parameters("NAME"  )->asString();	if( Name.Length() == 0 )	Name	= pShapes->Get_Name();

	Field		= "geometry";

	int	SRID	= Get_SRID();

	//-----------------------------------------------------
	if( !CSG_Shapes_OGIS_Converter::from_ShapeType(Type, pShapes->Get_Type(), pShapes->Get_Vertex_Type()) )
	{
		Error_Set(_TL("invalid or unsupported shape or vertex type"));

		return( false );
	}

	//-----------------------------------------------------
	Get_Connection()->Begin(SavePoint = Get_Connection()->is_Transaction() ? "SHAPES_SAVE" : "");

	//-----------------------------------------------------
	if( Get_Connection()->Table_Exists(Name) )
	{
		Message_Add(_TL("table already exists") + CSG_String(": ") + Name);

		switch( Parameters("EXISTS")->asInt() )
		{
		case 0:	// abort export
			return( false );

		case 1:	// replace existing table
			Message_Add(_TL("trying to drop table") + CSG_String(": ") + Name);

			if( !Get_Connection()->Table_Drop(Name, false) )
			{
				Message_Add(CSG_String(" ...") + _TL("failed") + "!");

				return( false );
			}

			break;

		case 2:	// append records, if table structure allows
			break;
		}
	}

	//-----------------------------------------------------
	if( !Get_Connection()->Table_Exists(Name) )
	{
		if( !Get_Connection()->Table_Create(Name, *pShapes, Get_Constraints(&Parameters, "SHAPES"), false) )
		{
			Error_Set(_TL("could not create table"));

			Get_Connection()->Rollback(SavePoint);

			return( false );
		}

		//-------------------------------------------------
		// SELECT AddGeometryColumn(<table_name>, <column_name>, <srid>, <type>, <dimension>)

		SQL.Printf(SG_T("SELECT AddGeometryColumn('%s', '%s', %d, '%s', %d)"),
			Name.c_str(), Field.c_str(), SRID, Type.c_str(),
			pShapes->Get_Vertex_Type() == SG_VERTEX_TYPE_XY  ? 2 :
			pShapes->Get_Vertex_Type() == SG_VERTEX_TYPE_XYZ ? 3 : 4
		);

		if( !Get_Connection()->Execute(SQL) )
		{
			Error_Set(_TL("could not create geometry field"));

			Get_Connection()->Rollback(SavePoint);

			return( false );
		}
	}

	//-----------------------------------------------------
	bool	bBinary	= Get_Connection()->has_Version(9);

	int		iShape, iField, nAdded;

	CSG_String	Insert	= "INSERT INTO \"" + Name + "\" (" + Field;

	for(iField=0; iField<pShapes->Get_Field_Count(); iField++)
	{
		Insert	+= CSG_String(", ") + pShapes->Get_Field_Name(iField);
	}

	Insert	+= ") VALUES (";

	//-----------------------------------------------------
	for(iShape=0, nAdded=0; iShape==nAdded && iShape<pShapes->Get_Count() && Set_Progress(iShape, pShapes->Get_Count()); iShape++)
	{
		CSG_Shape	*pShape	= pShapes->Get_Shape(iShape);

		if( pShape->is_Valid() )
		{
			SQL	= Insert;

			if( bBinary )
			{
				CSG_Bytes	WKB;

				CSG_Shapes_OGIS_Converter::to_WKBinary(pShape, WKB);

				SQL	+= "ST_GeomFromWKB(E'\\\\x" + WKB.toHexString() + CSG_String::Format("', %d)", SRID);
			}
			else
			{
				CSG_String	WKT;

				CSG_Shapes_OGIS_Converter::to_WKText(pShape, WKT);

				SQL	+= "ST_GeomFromText('" + WKT + CSG_String::Format("', %d)", SRID);
			}

			for(iField=0; iField<pShapes->Get_Field_Count(); iField++)
			{
				CSG_String	s = pShape->asString(iField);

				if( pShapes->Get_Field_Type(iField) == SG_DATATYPE_String )
				{
					if( 1 )
					{
						char	*_s	= NULL; if( s.to_ASCII(&_s) ) s = _s; SG_FREE_SAFE(_s);
					}

					s.Replace("'", "\"");

					s	= "'" + s + "'";
				}

				SQL	+= ", "  + s;
			}

			SQL	+= ")";

			if( Get_Connection()->Execute(SQL) )
			{
				nAdded++;
			}
			else
			{
				Message_Add(CSG_String::Format("%s [%d/%d]", _TL("could not save shape"), 1 + iShape, pShapes->Get_Count()));
			}
		}
	}

	//-----------------------------------------------------
	if( nAdded < pShapes->Get_Count() )
	{
		Message_Add(SQL);

		Get_Connection()->Rollback(SavePoint);

		return( false );
	}

	Get_Connection()->Commit(SavePoint);

	Get_Connection()->GUI_Update();

	Get_Connection()->Add_MetaData(*pShapes, Name);

	pShapes->Set_Modified(false);

	return( true );
}
예제 #7
0
//---------------------------------------------------------
bool CPointCloud_Create_SPCVF::On_Execute(void)
{
	CSG_Strings					sFiles;
	CSG_String					sFileInputList, sFileName;
	int							iMethodPaths;

	CSG_MetaData				SPCVF;
	CSG_Projection				projSPCVF;
	double						dNoData;
	std::vector<TSG_Data_Type>	vFieldTypes;
	std::vector<CSG_String>		vFieldNames;
	double						dBBoxXMin = std::numeric_limits<int>::max();
	double						dBBoxYMin = std::numeric_limits<int>::max();
	double						dBBoxXMax = std::numeric_limits<int>::min();
	double						dBBoxYMax = std::numeric_limits<int>::min();
	int							iSkipped = 0, iEmpty = 0;
	int							iDatasetCount = 0;
	double						dPointCount = 0.0;
	double						dZMin = std::numeric_limits<double>::max();
	double						dZMax = -std::numeric_limits<double>::max();

	//-----------------------------------------------------
	sFileName		= Parameters("FILENAME")->asString();
	iMethodPaths	= Parameters("METHOD_PATHS")->asInt();
	sFileInputList	= Parameters("INPUT_FILE_LIST")->asString();

	//-----------------------------------------------------
	if( !Parameters("FILES")->asFilePath()->Get_FilePaths(sFiles) && sFileInputList.Length() <= 0 )
	{
		SG_UI_Msg_Add_Error(_TL("Please provide some input files!"));
		return( false );
	}

	//-----------------------------------------------------
	if( sFiles.Get_Count() <= 0 )
	{
		CSG_Table	*pTable = new CSG_Table();

		if( !pTable->Create(sFileInputList, TABLE_FILETYPE_Text_NoHeadLine) )
		{
			SG_UI_Msg_Add_Error(_TL("Input file list could not be opened!"));
			delete( pTable );
			return( false );
		}

		sFiles.Clear();

		for (int i=0; i<pTable->Get_Record_Count(); i++)
		{
			sFiles.Add(pTable->Get_Record(i)->asString(0));
		}

		delete( pTable );
	}


	//-----------------------------------------------------
	SPCVF.Set_Name(SG_T("SPCVFDataset"));
	SPCVF.Add_Property(SG_T("Version"), SG_T("1.1"));
	
	switch( iMethodPaths )
	{
	default:
	case 0:		SPCVF.Add_Property(SG_T("Paths"), SG_T("absolute"));	break;
	case 1:		SPCVF.Add_Property(SG_T("Paths"), SG_T("relative"));	break;
	}

	//-----------------------------------------------------
	CSG_MetaData	*pSPCVFHeader	= SPCVF.Add_Child(			SG_T("Header"));

	CSG_MetaData	*pSPCVFFiles	= pSPCVFHeader->Add_Child(	SG_T("Datasets"));
	CSG_MetaData	*pSPCVFPoints	= pSPCVFHeader->Add_Child(	SG_T("Points"));
	CSG_MetaData	*pSRS			= pSPCVFHeader->Add_Child(	SG_T("SRS"));
	CSG_MetaData	*pSPCVFBBox		= pSPCVFHeader->Add_Child(	SG_T("BBox"));
	CSG_MetaData	*pSPCVFZStats	= pSPCVFHeader->Add_Child(	SG_T("ZStats"));
	CSG_MetaData	*pSPCVFNoData	= pSPCVFHeader->Add_Child(	SG_T("NoData"));
	CSG_MetaData	*pSPCVFAttr		= pSPCVFHeader->Add_Child(	SG_T("Attributes"));

	CSG_MetaData	*pSPCVFDatasets	= NULL;
	

	//-----------------------------------------------------
	for(int i=0; i<sFiles.Get_Count() && Set_Progress(i, sFiles.Get_Count()); i++)
	{
		CSG_PointCloud	*pPC		= SG_Create_PointCloud(sFiles[i]);

		//-----------------------------------------------------
		if( i==0 )		// first dataset determines projection, NoData value and table structure
		{
			projSPCVF	= pPC->Get_Projection();
			dNoData		= pPC->Get_NoData_Value();

			pSPCVFNoData->Add_Property(SG_T("Value"), dNoData);

			pSPCVFAttr->Add_Property(SG_T("Count"), pPC->Get_Field_Count());

			for(int iField=0; iField<pPC->Get_Field_Count(); iField++)
			{
				vFieldTypes.push_back(pPC->Get_Field_Type(iField));
				vFieldNames.push_back(pPC->Get_Field_Name(iField));

				CSG_MetaData	*pSPCVFField = pSPCVFAttr->Add_Child(CSG_String::Format(SG_T("Field_%d"), iField + 1));

				pSPCVFField->Add_Property(SG_T("Name"), pPC->Get_Field_Name(iField));
				pSPCVFField->Add_Property(SG_T("Type"), gSG_Data_Type_Identifier[pPC->Get_Field_Type(iField)]);

			}

			if( projSPCVF.is_Okay() )
			{
				pSRS->Add_Property(SG_T("Projection"), projSPCVF.Get_Name());
				pSRS->Add_Property(SG_T("WKT"), projSPCVF.Get_WKT());
			}
			else
			{
				pSRS->Add_Property(SG_T("Projection"), SG_T("Undefined Coordinate System"));
			}

			pSPCVFDatasets	= SPCVF.Add_Child(SG_T("Datasets"));
		}
		else		// validate projection, NoData value and table structure
		{
			bool	bSkip = false;

			if( pPC->Get_Field_Count() != (int)vFieldTypes.size() )
			{
				bSkip = true;
			}

			if( !bSkip && projSPCVF.is_Okay() )
			{
				if ( !pPC->Get_Projection().is_Okay() || SG_STR_CMP(pPC->Get_Projection().Get_WKT(), projSPCVF.Get_WKT()) )
				{
					bSkip = true;
				}
			}

			if( !bSkip )
			{
				for(int iField=0; iField<pPC->Get_Field_Count(); iField++)
				{
					if( pPC->Get_Field_Type(iField) != vFieldTypes.at(iField) )
					{
						bSkip = true;
						break;
					}

					if( SG_STR_CMP(pPC->Get_Field_Name(iField), vFieldNames.at(iField)) )
					{
						bSkip = true;
						break;
					}
				}
			}

			if( bSkip )
			{
				SG_UI_Msg_Add(CSG_String::Format(_TL("Skipping dataset %s because of incompatibility with the first input dataset!"), sFiles[i].c_str()), true);
				delete( pPC );
				iSkipped++;
				continue;
			}
		}

		//-----------------------------------------------------
		if( pPC->Get_Point_Count() <= 0 )
		{
			delete( pPC );
			iEmpty++;
			continue;
		}

		//-----------------------------------------------------
		CSG_MetaData	*pDataset	= pSPCVFDatasets->Add_Child(SG_T("PointCloud"));

		CSG_String		sFilePath;

		switch( iMethodPaths )
		{
		default:
		case 0:		sFilePath = SG_File_Get_Path_Absolute(sFiles.Get_String(i));									break;
		case 1:		sFilePath = SG_File_Get_Path_Relative(SG_File_Get_Path(sFileName), sFiles.Get_String(i));		break;
		}

		sFilePath.Replace(SG_T("\\"), SG_T("/"));

		pDataset->Add_Property(SG_T("File"), sFilePath);

		pDataset->Add_Property(SG_T("Points"), pPC->Get_Point_Count());

		pDataset->Add_Property(SG_T("ZMin"), pPC->Get_ZMin());
		pDataset->Add_Property(SG_T("ZMax"), pPC->Get_ZMax());

		//-----------------------------------------------------
		CSG_MetaData	*pBBox		= pDataset->Add_Child(SG_T("BBox"));

		pBBox->Add_Property(SG_T("XMin"), pPC->Get_Extent().Get_XMin());
		pBBox->Add_Property(SG_T("YMin"), pPC->Get_Extent().Get_YMin());
		pBBox->Add_Property(SG_T("XMax"), pPC->Get_Extent().Get_XMax());
		pBBox->Add_Property(SG_T("YMax"), pPC->Get_Extent().Get_YMax());

		if( dBBoxXMin > pPC->Get_Extent().Get_XMin() )
			dBBoxXMin = pPC->Get_Extent().Get_XMin();
		if( dBBoxYMin > pPC->Get_Extent().Get_YMin() )
			dBBoxYMin = pPC->Get_Extent().Get_YMin();
		if( dBBoxXMax < pPC->Get_Extent().Get_XMax() )
			dBBoxXMax = pPC->Get_Extent().Get_XMax();
		if( dBBoxYMax < pPC->Get_Extent().Get_YMax() )
			dBBoxYMax = pPC->Get_Extent().Get_YMax();
		
		iDatasetCount	+= 1;
		dPointCount		+= pPC->Get_Point_Count();

		if( dZMin > pPC->Get_ZMin() )
			dZMin = pPC->Get_ZMin();
		if( dZMax < pPC->Get_ZMax() )
			dZMax = pPC->Get_ZMax();


		delete( pPC );
	}

	//-----------------------------------------------------
	pSPCVFBBox->Add_Property(SG_T("XMin"), dBBoxXMin);
	pSPCVFBBox->Add_Property(SG_T("YMin"), dBBoxYMin);
	pSPCVFBBox->Add_Property(SG_T("XMax"), dBBoxXMax);
	pSPCVFBBox->Add_Property(SG_T("YMax"), dBBoxYMax);

	pSPCVFFiles->Add_Property(SG_T("Count"), iDatasetCount);
	pSPCVFPoints->Add_Property(SG_T("Count"), CSG_String::Format(SG_T("%.0f"), dPointCount));
	pSPCVFZStats->Add_Property(SG_T("ZMin"), dZMin);
	pSPCVFZStats->Add_Property(SG_T("ZMax"), dZMax);

	//-----------------------------------------------------
	if( !SPCVF.Save(sFileName) )
	{
		SG_UI_Msg_Add_Error(CSG_String::Format(_TL("Unable to save %s file!"), sFileName.c_str()));

		return( false );
	}

	//-----------------------------------------------------
	if( iSkipped > 0 )
	{
		SG_UI_Msg_Add(CSG_String::Format(_TL("WARNING: %d dataset(s) skipped because of incompatibilities!"), iSkipped), true);
	}

	if( iEmpty > 0 )
	{
		SG_UI_Msg_Add(CSG_String::Format(_TL("WARNING: %d dataset(s) skipped because they are empty!"), iEmpty), true);
	}

	SG_UI_Msg_Add(CSG_String::Format(_TL("SPCVF successfully created from %d dataset(s)."), iDatasetCount), true);

	//-----------------------------------------------------
	return( true );
}