<commit_before>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation. 
 * See the COPYING file for more information.
 *
 **********************************************************************
 * $Log$
 * Revision 1.8  2004/05/07 07:57:27  strk
 * Added missing EdgeNodingValidator to build scripts.
 * Changed SegmentString constructor back to its original form
 * (takes const void *), implemented local tracking of "contexts"
 * in caller objects for proper destruction.
 *
 * Revision 1.7  2004/05/06 15:54:15  strk
 * SegmentNodeList keeps track of created splitEdges for later destruction.
 * SegmentString constructor copies given Label.
 * Buffer operation does no more leaks for doc/example.cpp
 *
 * Revision 1.6  2004/05/05 13:08:01  strk
 * Leaks fixed, explicit allocations/deallocations reduced.
 *
 * Revision 1.5  2004/04/20 10:58:04  strk
 * More memory leaks removed.
 *
 * Revision 1.4  2004/04/20 10:14:20  strk
 * Memory leaks removed.
 *
 * Revision 1.3  2004/04/19 16:14:52  strk
 * Some memory leaks plugged in noding algorithms.
 *
 * Revision 1.2  2004/04/19 15:14:46  strk
 * Added missing virtual destructor in SpatialIndex class.
 * Memory leaks fixes. Const and throw specifications added.
 *
 * Revision 1.1  2004/04/10 08:40:01  ybychkov
 * "operation/buffer" upgraded to JTS 1.4
 *
 *
 **********************************************************************/


#include "../../headers/opBuffer.h"
#include <typeinfo>

namespace geos {

OffsetCurveSetBuilder::OffsetCurveSetBuilder(const Geometry *newInputGeom, double newDistance, OffsetCurveBuilder *newCurveBuilder){
	cga=new RobustCGAlgorithms();
	curveList=new vector<SegmentString*>();
	inputGeom=newInputGeom;
	distance=newDistance;
	curveBuilder=newCurveBuilder;
}

OffsetCurveSetBuilder::~OffsetCurveSetBuilder(){
	delete cga;
	for (int i=0; i<curveList->size(); i++)
		delete (*curveList)[i];
	delete curveList;
	for (int i=0; i<newLabels.size(); i++)
		delete newLabels[i];
}
/**
* Computes the set of raw offset curves for the buffer.
* Each offset curve has an attached {@link Label} indicating
* its left and right location.
*
* @return a Collection of SegmentStrings representing the raw buffer curves
*/
vector<SegmentString*>* OffsetCurveSetBuilder::getCurves(){
	add(inputGeom);
	return curveList;
}

void
OffsetCurveSetBuilder::addCurves(const vector<CoordinateList*> *lineList, int leftLoc, int rightLoc)
{
	for (int i=0;i<(int)lineList->size();i++) {
		const CoordinateList *coords=(*lineList)[i];
		addCurve(coords, leftLoc, rightLoc);
	}
}

/**
* Creates a {@link SegmentString} for a coordinate list which is a raw offset curve,
* and adds it to the list of buffer curves.
* The SegmentString is tagged with a Label giving the topology of the curve.
* The curve may be oriented in either direction.
* If the curve is oriented CW, the locations will be:
* <br>Left: Location.EXTERIOR
* <br>Right: Location.INTERIOR
*/
void
OffsetCurveSetBuilder::addCurve(const CoordinateList *coord, int leftLoc, int rightLoc)
{
	// don't add null curves!
	if (coord->getSize() < 2) return;
	// add the edge for a coordinate list which is a raw offset curve
	Label *newlabel = new Label(0, Location::BOUNDARY, leftLoc, rightLoc);
	SegmentString *e=new SegmentString(coord,newlabel);
	newLabels.push_back(newlabel);
	curveList->push_back(e);
}


void
OffsetCurveSetBuilder::add(const Geometry *g)
{
	if (g->isEmpty()) return;
	if (typeid(*g)==typeid(Polygon))
		addPolygon((Polygon*) g);
	else if (typeid(*g)==typeid(LineString))
		addLineString((LineString*) g);
	else if (typeid(*g)==typeid(LinearRing))
		addLineString((LineString*) g);
	else if (typeid(*g)==typeid(Point))
		addPoint((Point*) g);
	else if (typeid(*g)==typeid(MultiPoint))
		addCollection((MultiPoint*) g);
	else if (typeid(*g)==typeid(MultiLineString))
		addCollection((MultiLineString*) g);
	else if (typeid(*g)==typeid(MultiPolygon))
		addCollection((MultiPolygon*) g);
	else if (typeid(*g)==typeid(GeometryCollection))
		addCollection((GeometryCollection*) g);
	else {
		string out=typeid(*g).name();
		throw new UnsupportedOperationException("GeometryGraph::add(Geometry *): unknown geometry type: "+out);
	}
}

void OffsetCurveSetBuilder::addCollection(const GeometryCollection *gc){
	for (int i=0;i<gc->getNumGeometries(); i++) {
		const Geometry *g=gc->getGeometryN(i);
		add(g);
	}
}
/**
* Add a Point to the graph->
*/
void OffsetCurveSetBuilder::addPoint(const Point *p){
	if (distance <= 0.0) return;
	CoordinateList *coord=p->getCoordinates();
	vector<CoordinateList*> *lineList=curveBuilder->getLineCurve(coord, distance);
	delete coord;
	addCurves(lineList, Location::EXTERIOR, Location::INTERIOR);
	delete lineList;
}

void OffsetCurveSetBuilder::addLineString(const LineString *line){
	if (distance <= 0.0) return;
	CoordinateList *coord=CoordinateList::removeRepeatedPoints(line->getCoordinatesRO());
	vector<CoordinateList*> *lineList=curveBuilder->getLineCurve(coord, distance);
	delete coord;
	addCurves(lineList, Location::EXTERIOR, Location::INTERIOR);
	delete lineList;
}

void
OffsetCurveSetBuilder::addPolygon(const Polygon *p)
{
	double offsetDistance=distance;
	int offsetSide=Position::LEFT;
	if (distance < 0.0) {
		offsetDistance=-distance;
		offsetSide=Position::RIGHT;
	}
	const LinearRing *shell=(const LinearRing *)p->getExteriorRing();
	CoordinateList *shellCoord=CoordinateList::removeRepeatedPoints(shell->getCoordinatesRO());
	// optimization - don't bother computing buffer
	// if the polygon would be completely eroded
	if (distance < 0.0 && isErodedCompletely(shellCoord, distance))
	{
		delete shellCoord;
		return;
	}
	addPolygonRing(shellCoord,offsetDistance,offsetSide,Location::EXTERIOR,Location::INTERIOR);
	delete shellCoord;
	for (int i=0;i<p->getNumInteriorRing(); i++) {
		const LinearRing *hole=(const LinearRing *)p->getInteriorRingN(i);
		CoordinateList *holeCoord=CoordinateList::removeRepeatedPoints(hole->getCoordinatesRO());
		// optimization - don't bother computing buffer for this hole
		// if the hole would be completely covered
		if (distance > 0.0 && isErodedCompletely(holeCoord, -distance))
		{
			delete holeCoord;
			return;
		}
		// Holes are topologically labelled opposite to the shell, since<commit_msg>Bugfix in OffsetCurveSetBuilder::addPolygon (JTS 1.4.1)<commit_after>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation. 
 * See the COPYING file for more information.
 *
 **********************************************************************
 * $Log$
 * Revision 1.9  2004/05/19 09:57:54  ybychkov
 * Bugfix in OffsetCurveSetBuilder::addPolygon (JTS 1.4.1)
 *
 * Revision 1.8  2004/05/07 07:57:27  strk
 * Added missing EdgeNodingValidator to build scripts.
 * Changed SegmentString constructor back to its original form
 * (takes const void *), implemented local tracking of "contexts"
 * in caller objects for proper destruction.
 *
 * Revision 1.7  2004/05/06 15:54:15  strk
 * SegmentNodeList keeps track of created splitEdges for later destruction.
 * SegmentString constructor copies given Label.
 * Buffer operation does no more leaks for doc/example.cpp
 *
 * Revision 1.6  2004/05/05 13:08:01  strk
 * Leaks fixed, explicit allocations/deallocations reduced.
 *
 * Revision 1.5  2004/04/20 10:58:04  strk
 * More memory leaks removed.
 *
 * Revision 1.4  2004/04/20 10:14:20  strk
 * Memory leaks removed.
 *
 * Revision 1.3  2004/04/19 16:14:52  strk
 * Some memory leaks plugged in noding algorithms.
 *
 * Revision 1.2  2004/04/19 15:14:46  strk
 * Added missing virtual destructor in SpatialIndex class.
 * Memory leaks fixes. Const and throw specifications added.
 *
 * Revision 1.1  2004/04/10 08:40:01  ybychkov
 * "operation/buffer" upgraded to JTS 1.4
 *
 *
 **********************************************************************/


#include "../../headers/opBuffer.h"
#include <typeinfo>

namespace geos {

OffsetCurveSetBuilder::OffsetCurveSetBuilder(const Geometry *newInputGeom, double newDistance, OffsetCurveBuilder *newCurveBuilder){
	cga=new RobustCGAlgorithms();
	curveList=new vector<SegmentString*>();
	inputGeom=newInputGeom;
	distance=newDistance;
	curveBuilder=newCurveBuilder;
}

OffsetCurveSetBuilder::~OffsetCurveSetBuilder(){
	delete cga;
	for (int i=0; i<curveList->size(); i++)
		delete (*curveList)[i];
	delete curveList;
	for (int i=0; i<newLabels.size(); i++)
		delete newLabels[i];
}
/**
* Computes the set of raw offset curves for the buffer.
* Each offset curve has an attached {@link Label} indicating
* its left and right location.
*
* @return a Collection of SegmentStrings representing the raw buffer curves
*/
vector<SegmentString*>* OffsetCurveSetBuilder::getCurves(){
	add(inputGeom);
	return curveList;
}

void
OffsetCurveSetBuilder::addCurves(const vector<CoordinateList*> *lineList, int leftLoc, int rightLoc)
{
	for (int i=0;i<(int)lineList->size();i++) {
		const CoordinateList *coords=(*lineList)[i];
		addCurve(coords, leftLoc, rightLoc);
	}
}

/**
* Creates a {@link SegmentString} for a coordinate list which is a raw offset curve,
* and adds it to the list of buffer curves.
* The SegmentString is tagged with a Label giving the topology of the curve.
* The curve may be oriented in either direction.
* If the curve is oriented CW, the locations will be:
* <br>Left: Location.EXTERIOR
* <br>Right: Location.INTERIOR
*/
void
OffsetCurveSetBuilder::addCurve(const CoordinateList *coord, int leftLoc, int rightLoc)
{
	// don't add null curves!
	if (coord->getSize() < 2) return;
	// add the edge for a coordinate list which is a raw offset curve
	Label *newlabel = new Label(0, Location::BOUNDARY, leftLoc, rightLoc);
	SegmentString *e=new SegmentString(coord,newlabel);
	newLabels.push_back(newlabel);
	curveList->push_back(e);
}


void
OffsetCurveSetBuilder::add(const Geometry *g)
{
	if (g->isEmpty()) return;
	if (typeid(*g)==typeid(Polygon))
		addPolygon((Polygon*) g);
	else if (typeid(*g)==typeid(LineString))
		addLineString((LineString*) g);
	else if (typeid(*g)==typeid(LinearRing))
		addLineString((LineString*) g);
	else if (typeid(*g)==typeid(Point))
		addPoint((Point*) g);
	else if (typeid(*g)==typeid(MultiPoint))
		addCollection((MultiPoint*) g);
	else if (typeid(*g)==typeid(MultiLineString))
		addCollection((MultiLineString*) g);
	else if (typeid(*g)==typeid(MultiPolygon))
		addCollection((MultiPolygon*) g);
	else if (typeid(*g)==typeid(GeometryCollection))
		addCollection((GeometryCollection*) g);
	else {
		string out=typeid(*g).name();
		throw new UnsupportedOperationException("GeometryGraph::add(Geometry *): unknown geometry type: "+out);
	}
}

void OffsetCurveSetBuilder::addCollection(const GeometryCollection *gc){
	for (int i=0;i<gc->getNumGeometries(); i++) {
		const Geometry *g=gc->getGeometryN(i);
		add(g);
	}
}
/**
* Add a Point to the graph->
*/
void OffsetCurveSetBuilder::addPoint(const Point *p){
	if (distance <= 0.0) return;
	CoordinateList *coord=p->getCoordinates();
	vector<CoordinateList*> *lineList=curveBuilder->getLineCurve(coord, distance);
	delete coord;
	addCurves(lineList, Location::EXTERIOR, Location::INTERIOR);
	delete lineList;
}

void OffsetCurveSetBuilder::addLineString(const LineString *line){
	if (distance <= 0.0) return;
	CoordinateList *coord=CoordinateList::removeRepeatedPoints(line->getCoordinatesRO());
	vector<CoordinateList*> *lineList=curveBuilder->getLineCurve(coord, distance);
	delete coord;
	addCurves(lineList, Location::EXTERIOR, Location::INTERIOR);
	delete lineList;
}

void
OffsetCurveSetBuilder::addPolygon(const Polygon *p)
{
	double offsetDistance=distance;
	int offsetSide=Position::LEFT;
	if (distance < 0.0) {
		offsetDistance=-distance;
		offsetSide=Position::RIGHT;
	}
	const LinearRing *shell=(const LinearRing *)p->getExteriorRing();
	CoordinateList *shellCoord=CoordinateList::removeRepeatedPoints(shell->getCoordinatesRO());
	// optimization - don't bother computing buffer
	// if the polygon would be completely eroded
	if (distance < 0.0 && isErodedCompletely(shellCoord, distance))
	{
		delete shellCoord;
		return;
	}
	addPolygonRing(shellCoord,offsetDistance,offsetSide,Location::EXTERIOR,Location::INTERIOR);
	delete shellCoord;
	for (int i=0;i<p->getNumInteriorRing(); i++) {
		const LinearRing *hole=(const LinearRing *)p->getInteriorRingN(i);
		CoordinateList *holeCoord=CoordinateList::removeRepeatedPoints(hole->getCoordinatesRO());
		// optimization - don't bother computing buffer for this hole
		// if the hole would be completely covered
		if (distance > 0.0 && isErodedCompletely(holeCoord, -distance))
		{
//			delete holeCoord;
			continue;
		}
		// Holes are topologically labelled opposite to the shell, since
{'fraction_non_alphanumeric': 0.15102871354284422, 'fraction_numerical': 0.02502072499811591, 'mean_word_length': 5.5563241106719365, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3514743', 'n_tokens_mistral': 4509, 'n_tokens_neox': 4139, 'n_words': 1157}