/**********************************************************************
 * $Id: Label.cpp 2545 2009-06-05 12:07:52Z strk $
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2005-2006 Refractions Research Inc.
 * 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.
 *
 **********************************************************************
 *
 * Last port: geomgraph/Label.java rev. 1.8 (JTS-1.10)
 *
 **********************************************************************/

#include <geos/geomgraph/Label.h>
#include <geos/geomgraph/TopologyLocation.h>
#include <geos/geomgraph/Position.h>
#include <geos/geom/Location.h>

#include <string>
#include <sstream>
#include <iostream>
#include <cassert>


using namespace std;
using namespace geos::geom;

namespace geos {
namespace geomgraph { // geos.geomgraph

/*public static*/
Label*
Label::toLineLabel(const Label &label)
{
	Label *lineLabel=new Label(Location::UNDEF);
	for (int i=0; i<2; i++) {
		lineLabel->setLocation(i, label.getLocation(i));
	}
	return lineLabel;
}

/*public*/
Label::Label(int onLoc)
{
	elt[0]=TopologyLocation(onLoc);
	elt[1]=TopologyLocation(onLoc);
}

/*public*/
Label::Label(int geomIndex,int onLoc)
{
	assert(geomIndex>=0 && geomIndex<2);
	elt[0]=TopologyLocation(Location::UNDEF);
	elt[1]=TopologyLocation(Location::UNDEF);
	elt[geomIndex].setLocation(onLoc);
}

/*public*/
Label::Label(int onLoc,int leftLoc,int rightLoc)
{
	elt[0]=TopologyLocation(onLoc,leftLoc,rightLoc);
	elt[1]=TopologyLocation(onLoc,leftLoc,rightLoc);
}

/*public*/
Label::Label()
{
	elt[0]=TopologyLocation(Location::UNDEF);
	elt[1]=TopologyLocation(Location::UNDEF);
}

/*public*/
Label::Label(const Label &l)
{
	elt[0]=TopologyLocation(l.elt[0]);
	elt[1]=TopologyLocation(l.elt[1]);
}

/*public*/
Label::~Label()
{
}

/*public*/
Label::Label(int geomIndex,int onLoc,int leftLoc,int rightLoc)
{
	elt[0]=TopologyLocation(Location::UNDEF,Location::UNDEF,Location::UNDEF);
	elt[1]=TopologyLocation(Location::UNDEF,Location::UNDEF,Location::UNDEF);
	elt[geomIndex].setLocations(onLoc,leftLoc,rightLoc);
}

/*public*/
void
Label::flip()
{
	elt[0].flip();
	elt[1].flip();
}

/*public*/
int
Label::getLocation(int geomIndex, int posIndex) const
{
	assert(geomIndex>=0 && geomIndex<2);
	return elt[geomIndex].get(posIndex);
}

/*public*/
int
Label::getLocation(int geomIndex) const
{
	assert(geomIndex>=0 && geomIndex<2);
	return elt[geomIndex].get(Position::ON);
}

/*public*/
void
Label::setLocation(int geomIndex,int posIndex,int location)
{
	assert(geomIndex>=0 && geomIndex<2);
	elt[geomIndex].setLocation(posIndex,location);
}

/*public*/
void
Label::setLocation(int geomIndex,int location)
{
	assert(geomIndex>=0 && geomIndex<2);
	elt[geomIndex].setLocation(Position::ON,location);
}

/*public*/
void
Label::setAllLocations(int geomIndex,int location)
{
	assert(geomIndex>=0 && geomIndex<2);
	elt[geomIndex].setAllLocations(location);
}

/*public*/
void
Label::setAllLocationsIfNull(int geomIndex,int location)
{
	assert(geomIndex>=0 && geomIndex<2);
	elt[geomIndex].setAllLocationsIfNull(location);
}

/*public*/
void
Label::setAllLocationsIfNull(int location)
{
	setAllLocationsIfNull(0,location);
	setAllLocationsIfNull(1,location);
}

/*public*/
void
Label::merge(const Label &lbl)
{
	for (int i=0; i<2; i++) {
		elt[i].merge(lbl.elt[i]);
	}
}

/*public*/
int
Label::getGeometryCount() const
{
	int count = 0;
	if (!elt[0].isNull()) count++;
	if (!elt[1].isNull()) count++;
	return count;
}

/*public*/
bool
Label::isNull(int geomIndex) const
{
	assert(geomIndex>=0 && geomIndex<2);
	return elt[geomIndex].isNull();
}

/*public*/
bool
Label::isAnyNull(int geomIndex) const
{
	assert(geomIndex>=0 && geomIndex<2);
	return elt[geomIndex].isAnyNull();
}

/*public*/
bool
Label::isArea() const
{
	return elt[0].isArea() || elt[1].isArea();
}

/*public*/
bool
Label::isArea(int geomIndex) const
{
	assert(geomIndex>=0 && geomIndex<2);
	return elt[geomIndex].isArea();
}

/*public*/
bool
Label::isLine(int geomIndex) const
{
	assert(geomIndex>=0 && geomIndex<2);
	return elt[geomIndex].isLine();
}

/*public*/
bool
Label::isEqualOnSide(const Label& lbl, int side) const
{
	return 
		elt[0].isEqualOnSide(lbl.elt[0], side)
		&& elt[1].isEqualOnSide(lbl.elt[1], side);
}

/*public*/
bool
Label::allPositionsEqual(int geomIndex, int loc) const
{
	assert(geomIndex>=0 && geomIndex<2);
	return elt[geomIndex].allPositionsEqual(loc);
}

/*public*/
void
Label::toLine(int geomIndex)
{
	assert(geomIndex>=0 && geomIndex<2);
	if (elt[geomIndex].isArea()) {
		elt[geomIndex]=TopologyLocation(elt[geomIndex].getLocations()[0]);
	}
}

string
Label::toString() const
{
	stringstream ss;
	ss << *this;
	return ss.str();
}

std::ostream&
operator<< (std::ostream& os, const Label& l)
{
	os << "A:"
	   << l.elt[0]
	   << " B:"
	   << l.elt[1];
	return os;
}

} // namespace geos.geomgraph
} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.10  2006/04/06 09:01:37  strk
 * Doxygen comments, port info, operator<<, assertion checking
 *
 * Revision 1.9  2006/04/03 17:05:22  strk
 * Assertion checking, port info, cleanups
 *
 * Revision 1.8  2006/03/14 12:55:55  strk
 * Headers split: geomgraphindex.h, nodingSnapround.h
 *
 * Revision 1.7  2006/03/03 10:46:21  strk
 * Removed 'using namespace' from headers, added missing headers in .cpp files, removed useless includes in headers (bug#46)
 *
 * Revision 1.6  2006/02/19 19:46:49  strk
 * Packages <-> namespaces mapping for most GEOS internal code (uncomplete, but working). Dir-level libs for index/ subdirs.
 *
 **********************************************************************/

