void end( const TWallVertexVector& vb, TIntVector& polygon, TIntVector& ib )
	{
		assert( polygonCount );
		if( polygonCount == 1 ) {
			
			// trivial case, just output input polygon
			polygon.resize( 0 );
			polygon.reserve( vertices.size() );
			int idx0 = *vertices.begin();
			int idx = idx0;
			do {
				polygon.push_back( idx );
				const TIntVector& vnext = vertexNexts[idx];
				assert( vnext.size() == 1 );
				idx = vnext[0];
			} while( idx != idx0 );


			triangulator::process( vb, polygon, ib );

		} else {
			
			// mark vertex types
			markVertexTypes();

			// trace and triangulate the polygon(s)
			traceBorder( vb, polygon, ib );
		}
	}
	void	markVertexTypes()
	{
		TIntSet::const_iterator vit, vitEnd = vertices.end();

		// first pass: mark all interior and single-border vertices
		for( vit = vertices.begin(); vit != vitEnd; ++vit ) {
			int idx = *vit;
			if( vertexUseCount[idx] == 1 ) {
				vertexTypes[idx] = VTYPE_SINGLE;
				borderVertices.insert( idx );
			} else if( isVertexInterior(idx) )
				vertexTypes[idx] = VTYPE_INTERIOR;
		}

		// now, the unmarked vertices are all shared and on border
		for( vit = vertices.begin(); vit != vitEnd; ++vit ) {
			int idx = *vit;
			if( vertexTypes[idx] == VTYPE_NONE ) {
				vertexTypes[idx] = VTYPE_MULTI;
				borderVertices.insert( idx );
			}
		}
	}
	int		getBorderIndex()
	{
		if( borderVertices.empty() )
			return -1;
		return *borderVertices.begin();
	}