dmpvectorlayer.cpp 9.9 KB
/**************************************************************************
* file:              dmpvectorlayer.cpp

* Author:            wanzhongping
* Date:              2021-07-05 16:37:23
* Email:             zhongpingw@chinadci.com
* copyright:         广州城市信息研究所有限公司
***************************************************************************/
#include "dmpvectorlayer.h"
#include "dmpxmlutils.h"
#include "dmpvectorlayerrenderer.h"
#include "dmpproviderregistry.h"
#include "libpq-fe.h"
#include "clsUtil.h"
#include <boost/algorithm/string/predicate.hpp>

DmpVectorLayer::DmpVectorLayer(const std::string &path,
							   const std::string &baseName,
							   const std::string &providerKey,
							   const DmpVectorLayer::LayerOptions &options)
	: DmpMapLayer(DmpMapLayerType::VectorLayer, baseName, path), readExtentFromXml_(options.readExtentFromXml)
{
	wkbType_ = options.fallbackWkbType;
	setProviderType(providerKey);

	if (!path.empty() && !providerKey.empty())
	{
		setDataSource(path, baseName, providerKey, options.loadDefaultStyle);
	}
}

DmpVectorLayer::~DmpVectorLayer()
{
}

DmpMapLayerRenderer *DmpVectorLayer::createMapRenderer(DmpRenderContext &rendererContext)
{
	return new DmpVectorLayerRenderer(this, rendererContext);
}

bool DmpVectorLayer::readXml(const boost::property_tree::ptree &layerNode)
{
	//id="gzxxd_aabe200b_5b63_4b82_8546_af1fc99e4ec6" name="gzxxd" alias="中学" type="1"
	// geometry="Point" alwaysShow="true" maxScale="0" maxScale="50000"
	id_ = layerNode.get<std::string>("<xmlattr>.id");
	name_ = layerNode.get<std::string>("<xmlattr>.name");
	title_ = layerNode.get<std::string>("<xmlattr>.alias");
	boost::property_tree::ptree pExtent = layerNode.get_child("extent");
	extent_ = DmpXmlUtils::readRectangle(pExtent);
	dataSource_ = layerNode.get<std::string>("datasource");

	if (!setDataProvider(dataSource_))
	{
		schema_ = layerNode.get<std::string>("<xmlattr>.schema");
		geom_ = layerNode.get<std::string>("<xmlattr>.geomfield");
		wkbTypeString_ = layerNode.get<std::string>("<xmlattr>.geometry");
		featurecount_ = layerNode.get<unsigned int>("<xmlattr>.featurecount");
		srid_ = layerNode.get<std::string>("<xmlattr>.srid");
	}

	if (boost::iequals(wkbTypeString_, "POINT"))
		wkbType_ = DmpWkbTypes::Point;
	else if (boost::iequals(wkbTypeString_, "MULTIPOINT"))
		wkbType_ = DmpWkbTypes::MultiPoint;
	else if (boost::iequals(wkbTypeString_, "LINESTRING") || boost::iequals(wkbTypeString_, "LINE") )
		wkbType_ = DmpWkbTypes::LineString;
	else if (boost::iequals(wkbTypeString_, "MULTILINESTRING")|| boost::iequals(wkbTypeString_, "MULTILINE") )
		wkbType_ = DmpWkbTypes::MultiLineString;
	else if (boost::iequals(wkbTypeString_, "POLYGON"))
		wkbType_ = DmpWkbTypes::Polygon;
	else if (boost::iequals(wkbTypeString_, "MULTIPOLYGON"))
		wkbType_ = DmpWkbTypes::MultiPolygon;
	else if (boost::iequals(wkbTypeString_, "GEOMETRY"))
		wkbType_ = DmpWkbTypes::Unknown;

	boost::property_tree::ptree ptRenderer = layerNode.get_child("renderer");
	auto pIter = ptRenderer.begin();
	if (pIter == ptRenderer.end())
		return false;
	DmapCore_30::Renderer *renderer_30 = nullptr;
	DmapCore_30::clsXML::XMLParse(pIter->first, pIter->second, &renderer_30);
	renderer_30_ = shared_ptr<DmapCore_30::Renderer>(renderer_30);

	// geom_ = "geom";
	// schema_ = "public";
	// wkbType_ = DmpWkbTypes::MultiLineString;

	return true;
}

bool DmpVectorLayer::writeXml(boost::property_tree::ptree &layerNode)
{
	layerNode.add("<xmlattr>.id", id_);
	layerNode.add("<xmlattr>.name", name_);
	layerNode.add("<xmlattr>.alias", title_);
	
	layerNode.add("<xmlattr>.schema",schema_ );
	layerNode.add("<xmlattr>.geomfield",geom_ );
	layerNode.add("<xmlattr>.featurecount",featurecount_ );
	layerNode.add("<xmlattr>.geometry",wkbTypeString_ );
	layerNode.add("<xmlattr>.srid",srid_ );


	boost::property_tree::ptree ptExtent;
	ptExtent.add("xmin", extent_.xmin());
	ptExtent.add("ymin", extent_.ymin());
	ptExtent.add("xmax", extent_.xmax());
	ptExtent.add("ymax", extent_.ymax());
	layerNode.add_child("extent", ptExtent);

	layerNode.add("datasource", dataSource_);
	boost::property_tree::ptree ptRenderer;
	if (this->renderer_30_)
	{
		this->renderer_30_->ParsePtree(ptRenderer);
	}
	layerNode.add_child("renderer", ptRenderer);

	return true;
}

bool DmpVectorLayer::writejson(std::string &json)
{
	string shapeTypeString = "UNKNOWORD";

	switch (wkbType_)
	{
	case DmpWkbTypes::Point:
		shapeTypeString = "POINT";
		break;
	case DmpWkbTypes::MultiPoint:
		shapeTypeString = "MULTIPOINT";
		break;
	case DmpWkbTypes::LineString:
		shapeTypeString = "LINESTRING";
		break;
	case DmpWkbTypes::MultiLineString:
		shapeTypeString = "MULTILINESTRING";
		break;
	case DmpWkbTypes::Polygon:
		shapeTypeString = "POLYGON";
		break;
	case DmpWkbTypes::MultiPolygon:
		shapeTypeString = "MULTIPOLYGON";
		break;
	default:
		shapeTypeString = "UNKNOWORD";
		break;
	}

	bool alwaysShow = this->minScale() == 0 && this->maxScale() > 10000000000;
	char buff_maxscale[100];
	char buff_minscale[100];
	if (this->maxScale() > 100000000)
	{
		sprintf(buff_maxscale, "%e", this->maxScale());
	}
	else
	{
		sprintf(buff_maxscale, "%.0f", this->maxScale());
	}

	if (this->minScale() > 100000000)
	{
		sprintf(buff_minscale, "%e", this->minScale());
	}
	else
	{
		sprintf(buff_minscale, "%.0f", this->minScale());
	}
	//Display scale setting  type="1" geometry="Point" alwaysShow="true" maxScale="0" maxScale="50000">

	char resultbuff[1000];
	string json_source = this->source();
	DmapCore_30::clsUtil::ToJSONString(json_source);
	sprintf(resultbuff,
			R"({"workspace":"","type":"1","dbsource":"%s","data":"","schema":"%s",
"alias":"%s","name":"%s","id":"%s","filter":"%s","visible":"%s","tag":"","minScale":"%s",
"maxScale":"%s","geometry":"%s","alwaysShow":"%s","geomfield":"%s","srid":"%s","featurecount":"%ld")",
			json_source.c_str(),
			this->schema().c_str(),
			this->title().c_str(),
			this->name().c_str(),
			this->id().c_str(),
			this->wherestr_.c_str(),
			"true",
			buff_minscale, buff_maxscale,
			shapeTypeString.c_str(),
			alwaysShow ? "true" : "false",
			geom_.c_str(),
			srid_.c_str(),
            featurecount_
			);

	json.append(resultbuff);
	if (this->renderer_30_ != nullptr)
	{

		json.append(",");
		DmapCore_30::AppendBuffer ab;
		this->renderer_30_->ToJson(&ab);
		json.append(ab.GetString());
	}
	json.append("}");
	return true;
}

void DmpVectorLayer::setRenderer(DmpFeatureRenderer *renderer)
{
}

void DmpVectorLayer::setDataSource(const std::string &dataSource, const std::string &baseName, const std::string &provider, bool loadDefaultStyleFlag)
{
	DmpWkbTypes::GeometryType geomType = GeometryType();
}

DmpWkbTypes::GeometryType DmpVectorLayer::GeometryType() const
{
	return DmpWkbTypes::GeometryType(wkbType_);
}

bool DmpVectorLayer::setDataProvider(const std::string &provider)
{
	if (provider.size() < 50)
		return false;
	isinit_ = true;
	//临时测试使用
	PGconn *pPGconn = PQconnectdb(provider.c_str());
	ConnStatusType t = PQstatus(pPGconn);
	if (t != CONNECTION_OK)
		return false;
	int re = PQsetClientEncoding(pPGconn, "UTF-8");

	std::string sql = "select  t.f_geometry_column, t.type ,f_table_schema,t.srid from public.geometry_columns t where lower( t.f_table_name) = lower('" + name_ + "');";
	PGresult *pPGresult = PQexec(pPGconn, sql.c_str());
	char *sz = PQerrorMessage(pPGconn);
	if (sz != nullptr && strcmp(sz, "") != 0)
	{
		PQfinish(pPGconn);
		return false;
	}

	int rowCount = PQntuples(pPGresult);
	if (rowCount < 1)
	{
		PQfinish(pPGconn);
		return false;
	}

	geom_ = PQgetvalue(pPGresult, 0, 0);
	const char *geomtype = PQgetvalue(pPGresult, 0, 1);
	schema_ = PQgetvalue(pPGresult, 0, 2);
	std::string srid = PQgetvalue(pPGresult, 0, 3);
	wkbTypeString_ = geomtype;
	srid_ = srid;
	if (!geomtype)
		return false;
	if (!strcmp(geomtype, "POINT"))
		wkbType_ = DmpWkbTypes::Point;
	else if (!strcmp(geomtype, "MULTIPOINT"))
		wkbType_ = DmpWkbTypes::MultiPoint;
	else if (!strcmp(geomtype, "LINESTRING"))
		wkbType_ = DmpWkbTypes::LineString;
	else if (!strcmp(geomtype, "MULTILINESTRING"))
		wkbType_ = DmpWkbTypes::MultiLineString;
	else if (!strcmp(geomtype, "POLYGON"))
		wkbType_ = DmpWkbTypes::Polygon;
	else if (!strcmp(geomtype, "MULTIPOLYGON"))
		wkbType_ = DmpWkbTypes::MultiPolygon;
	else if (!strcmp(geomtype, "GEOMETRY"))
		wkbType_ = DmpWkbTypes::Unknown;
	PQclear(pPGresult);
	pPGresult = NULL;
	PQfinish(pPGconn);

	return true;

	providerKey_ = provider;
	delete dataProvider_;

	dataProvider_ = dynamic_cast<DmpVectorDataProvider *>(DmpProviderRegistry::Instance(provider)->CreateProvider(provider, dataSource_));
	if (!dataProvider_)
	{
		isValid_ = false;
		return false;
	}
	isValid_ = dataProvider_->IsValid();
	if (!isValid_)
	{
		return false;
	}
	wkbType_ = dataProvider_->WkbType();
	return true;
}

shared_ptr<DmpVectorThinLayer> DmpVectorLayer::GetCurrentScaleTable(double dx)
{

	/*
		int outTime = 600;
		if(this->dataCount >500000 && this->m_pDataset->m_MapLayerThinning.size() ==0)
		{
            outTime = 20;
		}	
		
		clsLockClass lock(_wlock);
		time_t now = time(0);
			//shared_ptr<WMSServer> wmsServer = this->m_mapWmsServer[servicename];
		if(now - this->m_pDataset->m_loadMapLayerThinning >  outTime)
		{
			this->m_pDataset->m_loadMapLayerThinning = now;
			shared_ptr<Workspace> pWorkspaceDef = DataSourcePools::get_instance()->GetDefaultWorkspace();

			this->m_pDataset->InitMapLayerThinning(pWorkspaceDef.get(),this->m_layerName, this->m_dbSource);
		}
		else
		{
			this->m_pDataset->m_loadMapLayerThinning = now;
		}
*/

	for (int i = 0; i < this->thinLayers_.size(); i++)
	{
		shared_ptr<DmpVectorThinLayer> mapLayerThinning = this->thinLayers_[i];

		if (mapLayerThinning->IsCurrentLayer(dx))
		{
			return mapLayerThinning;
		}
	}
	return nullptr;
}