//! \exception std::runtime_error will be thrown if \a inRegion overlaps an
//!     existing region.
//!
//! \todo Need to investigate if we can use the STL sort algorithm at all. Even
//!     though we're doing merges too, we could sort first then examine the list
//!     for merges.
void StExecutableImage::insertOrMergeRegion(MemoryRegion &inRegion)
{
    uint32_t newStart = inRegion.m_address;
    uint32_t newEnd = newStart + inRegion.m_length;

    MemoryRegionList::iterator it = m_image.begin();

    for (; it != m_image.end(); ++it)
    {
        MemoryRegion &region = *it;
        uint32_t thisStart = region.m_address;
        uint32_t thisEnd = thisStart + region.m_length;

        // keep track of where to insert it to retain sort order
        if (thisStart >= newEnd)
        {
            break;
        }

        // region types and flags must match in order to merge
        if (region.m_type == inRegion.m_type && region.m_flags == inRegion.m_flags)
        {
            if (newStart == thisEnd || newEnd == thisStart)
            {
                mergeRegions(region, inRegion);
                return;
            }
            else if ((newStart >= thisStart && newStart < thisEnd) || (newEnd >= thisStart && newEnd < thisEnd))
            {
                throw std::runtime_error("new region overlaps existing region");
            }
        }
    }

    // not merged, so just insert it in the sorted position
    m_image.insert(it, inRegion);
}
static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegionSize,
                               unsigned short& maxRegionId,
                               rcCompactHeightfield& chf,
                               unsigned short* srcReg)
{
    const int w = chf.width;
    const int h = chf.height;
    
    const int nreg = maxRegionId+1;
    rcRegion* regions = (rcRegion*)rcAlloc(sizeof(rcRegion)*nreg, RC_ALLOC_TEMP);
    if (!regions)
    {
        ctx->log(RC_LOG_ERROR, "filterSmallRegions: Out of memory 'regions' (%d).", nreg);
        return false;
    }

    // Construct regions
    for (int i = 0; i < nreg; ++i)
        new(&regions[i]) rcRegion((unsigned short)i);
    
    // Find edge of a region and find connections around the contour.
    for (int y = 0; y < h; ++y)
    {
        for (int x = 0; x < w; ++x)
        {
            const rcCompactCell& c = chf.cells[x+y*w];
            for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
            {
                unsigned short r = srcReg[i];
                if (r == 0 || r >= nreg)
                    continue;
                
                rcRegion& reg = regions[r];
                reg.spanCount++;
                
                
                // Update floors.
                for (int j = (int)c.index; j < ni; ++j)
                {
                    if (i == j) continue;
                    unsigned short floorId = srcReg[j];
                    if (floorId == 0 || floorId >= nreg)
                        continue;
                    addUniqueFloorRegion(reg, floorId);
                }
                
                // Have found contour
                if (reg.connections.size() > 0)
                    continue;
                
                reg.areaType = chf.areas[i];
                
                // Check if this cell is next to a border.
                int ndir = -1;
                for (int dir = 0; dir < 4; ++dir)
                {
                    if (isSolidEdge(chf, srcReg, x, y, i, dir))
                    {
                        ndir = dir;
                        break;
                    }
                }
                
                if (ndir != -1)
                {
                    // The cell is at border.
                    // Walk around the contour to find all the neighbours.
                    walkContour(x, y, i, ndir, chf, srcReg, reg.connections);
                }
            }
        }
    }

    // Remove too small regions.
    rcIntArray stack(32);
    rcIntArray trace(32);
    for (int i = 0; i < nreg; ++i)
    {
        rcRegion& reg = regions[i];
        if (reg.id == 0 || (reg.id & RC_BORDER_REG))
            continue;                       
        if (reg.spanCount == 0)
            continue;
        if (reg.visited)
            continue;
        
        // Count the total size of all the connected regions.
        // Also keep track of the regions connects to a tile border.
        bool connectsToBorder = false;
        int spanCount = 0;
        stack.resize(0);
        trace.resize(0);

        reg.visited = true;
        stack.push(i);
        
        while (stack.size())
        {
            // Pop
            int ri = stack.pop();
            
            rcRegion& creg = regions[ri];

            spanCount += creg.spanCount;
            trace.push(ri);

            for (int j = 0; j < creg.connections.size(); ++j)
            {
                if (creg.connections[j] & RC_BORDER_REG)
                {
                    connectsToBorder = true;
                    continue;
                }
                rcRegion& neireg = regions[creg.connections[j]];
                if (neireg.visited)
                    continue;
                if (neireg.id == 0 || (neireg.id & RC_BORDER_REG))
                    continue;
                // Visit
                stack.push(neireg.id);
                neireg.visited = true;
            }
        }
        
        // If the accumulated regions size is too small, remove it.
        // Do not remove areas which connect to tile borders
        // as their size cannot be estimated correctly and removing them
        // can potentially remove necessary areas.
        if (spanCount < minRegionArea && !connectsToBorder)
        {
            // Kill all visited regions.
            for (int j = 0; j < trace.size(); ++j)
            {
                regions[trace[j]].spanCount = 0;
                regions[trace[j]].id = 0;
            }
        }
    }
        
    // Merge too small regions to neighbour regions.
    int mergeCount = 0 ;
    do
    {
        mergeCount = 0;
        for (int i = 0; i < nreg; ++i)
        {
            rcRegion& reg = regions[i];
            if (reg.id == 0 || (reg.id & RC_BORDER_REG))
                continue;                       
            if (reg.spanCount == 0)
                continue;
            
            // Check to see if the region should be merged.
            if (reg.spanCount > mergeRegionSize && isRegionConnectedToBorder(reg))
                continue;
            
            // Small region with more than 1 connection.
            // Or region which is not connected to a border at all.
            // Find smallest neighbour region that connects to this one.
            int smallest = 0xfffffff;
            unsigned short mergeId = reg.id;
            for (int j = 0; j < reg.connections.size(); ++j)
            {
                if (reg.connections[j] & RC_BORDER_REG) continue;
                rcRegion& mreg = regions[reg.connections[j]];
                if (mreg.id == 0 || (mreg.id & RC_BORDER_REG)) continue;
                if (mreg.spanCount < smallest &&
                    canMergeWithRegion(reg, mreg) &&
                    canMergeWithRegion(mreg, reg))
                {
                    smallest = mreg.spanCount;
                    mergeId = mreg.id;
                }
            }
            // Found new id.
            if (mergeId != reg.id)
            {
                unsigned short oldId = reg.id;
                rcRegion& target = regions[mergeId];
                
                // Merge neighbours.
                if (mergeRegions(target, reg))
                {
                    // Fixup regions pointing to current region.
                    for (int j = 0; j < nreg; ++j)
                    {
                        if (regions[j].id == 0 || (regions[j].id & RC_BORDER_REG)) continue;
                        // If another region was already merged into current region
                        // change the nid of the previous region too.
                        if (regions[j].id == oldId)
                            regions[j].id = mergeId;
                        // Replace the current region with the new one if the
                        // current regions is neighbour.
                        replaceNeighbour(regions[j], oldId, mergeId);
                    }
                    mergeCount++;
                }
            }
        }
    }
    while (mergeCount > 0);
    
    // Compress region Ids.
    for (int i = 0; i < nreg; ++i)
    {
        regions[i].remap = false;
        if (regions[i].id == 0) continue;       // Skip nil regions.
        if (regions[i].id & RC_BORDER_REG) continue;    // Skip external regions.
        regions[i].remap = true;
    }
    
    unsigned short regIdGen = 0;
    for (int i = 0; i < nreg; ++i)
    {
        if (!regions[i].remap)
            continue;
        unsigned short oldId = regions[i].id;
        unsigned short newId = ++regIdGen;
        for (int j = i; j < nreg; ++j)
        {
            if (regions[j].id == oldId)
            {
                regions[j].id = newId;
                regions[j].remap = false;
            }
        }
    }
    maxRegionId = regIdGen;
    
    // Remap regions.
    for (int i = 0; i < chf.spanCount; ++i)
    {
        if ((srcReg[i] & RC_BORDER_REG) == 0)
            srcReg[i] = regions[srcReg[i]].id;
    }
    
    for (int i = 0; i < nreg; ++i)
        regions[i].~rcRegion();
    rcFree(regions);
    
    return true;
}
static bool filterSmallRegions(int minRegionSize, int mergeRegionSize,
							   unsigned short& maxRegionId,
							   rcCompactHeightfield& chf,
							   unsigned short* src)
{
	const int w = chf.width;
	const int h = chf.height;

	int nreg = maxRegionId+1;
	rcRegion* regions = new rcRegion[nreg];
	if (!regions)
	{
		if (rcGetLog())
			rcGetLog()->log(RC_LOG_ERROR, "filterSmallRegions: Out of memory 'regions' (%d).", nreg);
		return false;
	}
	
	for (int i = 0; i < nreg; ++i)
		regions[i].id = (unsigned short)i;

	// Find edge of a region and find connections around the contour.
	for (int y = 0; y < h; ++y)
	{
		for (int x = 0; x < w; ++x)
		{
			const rcCompactCell& c = chf.cells[x+y*w];
			for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
			{
				unsigned short r = src[i*2];
				if (r == 0 || r >= nreg)
					continue;
				
				rcRegion& reg = regions[r];
				reg.count++;
				

				// Update floors.
				for (int j = (int)c.index; j < ni; ++j)
				{
					if (i == j) continue;
					unsigned short floorId = src[j*2];
					if (floorId == 0 || floorId >= nreg)
						continue;
					addUniqueFloorRegion(reg, floorId);
				}
				
				// Have found contour
				if (reg.connections.size() > 0)
					continue;
				
				// Check if this cell is next to a border.
				int ndir = -1;
				for (int dir = 0; dir < 4; ++dir)
				{
					if (isSolidEdge(chf, src, x, y, i, dir))
					{
						ndir = dir;
						break;
					}
				}
				
				if (ndir != -1)
				{
					// The cell is at border.
					// Walk around the contour to find all the neighbours.
					walkContour(x, y, i, ndir, chf, src, reg.connections);
				}
			}
		}
	}
	
	// Remove too small unconnected regions.
	for (int i = 0; i < nreg; ++i)
	{
		rcRegion& reg = regions[i];
		if (reg.id == 0 || (reg.id & RC_BORDER_REG))
			continue;			
		if (reg.count == 0)
			continue;
		
		if (reg.connections.size() == 1 && reg.connections[0] == 0)
		{
			if (reg.count < minRegionSize)
			{
				// Non-connected small region, remove.
				reg.count = 0;
				reg.id = 0;
			}
		}
	}
		
		
	// Merge too small regions to neighbour regions.
	int mergeCount = 0 ;
	do
	{
		mergeCount = 0;
		for (int i = 0; i < nreg; ++i)
		{
			rcRegion& reg = regions[i];
			if (reg.id == 0 || (reg.id & RC_BORDER_REG))
				continue;			
			if (reg.count == 0)
				continue;
				
			// Check to see if the region should be merged.
			if (reg.count > mergeRegionSize && isRegionConnectedToBorder(reg))
				continue;
				
			// Small region with more than 1 connection.
			// Or region which is not connected to a border at all.
			// Find smallest neighbour region that connects to this one.
			int smallest = 0xfffffff;
			unsigned short mergeId = reg.id;
			for (int j = 0; j < reg.connections.size(); ++j)
			{
				if (reg.connections[j] & RC_BORDER_REG) continue;
				rcRegion& mreg = regions[reg.connections[j]];
				if (mreg.id == 0 || (mreg.id & RC_BORDER_REG)) continue;
				if (mreg.count < smallest &&
					canMergeWithRegion(reg, mreg.id) &&
					canMergeWithRegion(mreg, reg.id))
				{
					smallest = mreg.count;
					mergeId = mreg.id;
				}
			}
			// Found new id.
			if (mergeId != reg.id)
			{
				unsigned short oldId = reg.id;
				rcRegion& target = regions[mergeId];
				
				// Merge neighbours.
				if (mergeRegions(target, reg))
				{
					// Fixup regions pointing to current region.
					for (int j = 0; j < nreg; ++j)
					{
						if (regions[j].id == 0 || (regions[j].id & RC_BORDER_REG)) continue;
						// If another region was already merged into current region
						// change the nid of the previous region too.
						if (regions[j].id == oldId)
							regions[j].id = mergeId;
						// Replace the current region with the new one if the
						// current regions is neighbour.
						replaceNeighbour(regions[j], oldId, mergeId);
					}
					mergeCount++;
				}
			}
		}
	}
	while (mergeCount > 0);

	// Compress region Ids.
	for (int i = 0; i < nreg; ++i)
	{
		regions[i].remap = false;
		if (regions[i].id == 0) continue;	// Skip nil regions.
		if (regions[i].id & RC_BORDER_REG) continue;	// Skip external regions.
		regions[i].remap = true;
	}

	unsigned short regIdGen = 0;
	for (int i = 0; i < nreg; ++i)
	{
		if (!regions[i].remap)
			continue;
		unsigned short oldId = regions[i].id;
		unsigned short newId = ++regIdGen;
		for (int j = i; j < nreg; ++j)
		{
			if (regions[j].id == oldId)
			{
				regions[j].id = newId;
				regions[j].remap = false;
			}
		}
	}
	maxRegionId = regIdGen;
		
	// Remap regions.
	for (int i = 0; i < chf.spanCount; ++i)
	{
		if ((src[i*2] & RC_BORDER_REG) == 0)
			src[i*2] = regions[src[i*2]].id;
	}
	
	delete [] regions;
	
	return true;
}
static dtStatus filterSmallRegions(dtTileCacheAlloc* alloc, dtTileCacheLayer& layer, int minRegionArea, int mergeRegionSize,
                                   unsigned short& maxRegionId, unsigned short* srcReg)
{
    const int w = (int)layer.header->width;
    const int h = (int)layer.header->height;

    const int nreg = maxRegionId+1;
    dtFixedArray<dtLayerRegion> regions(alloc, nreg);
    if (!regions)
    {
        return DT_FAILURE | DT_OUT_OF_MEMORY;
    }

    // Construct regions
    regions.set(0);
    for (int i = 0; i < nreg; ++i)
        regions[i] = dtLayerRegion((unsigned short)i);

    // Find edge of a region and find connections around the contour.
    for (int y = 0; y < h; ++y)
    {
        const bool borderY = (y == 0) || (y == (h - 1));
        for (int x = 0; x < w; ++x)
        {
            const int i = x+y*w;
            unsigned short r = srcReg[i];

            if (r == DT_TILECACHE_NULL_AREA || r >= nreg)
                continue;

            dtLayerRegion& reg = regions[r];
            reg.cellCount++;
            reg.border |= borderY || (x == 0) || (x == (w - 1));

            // Have found contour
            if (reg.connections.size() > 0)
                continue;

            reg.areaType = layer.areas[i];

            // Check if this cell is next to a border.
            int ndir = -1;
            for (int dir = 0; dir < 4; ++dir)
            {
                if (isSolidEdge(layer, srcReg, x, y, i, dir))
                {
                    ndir = dir;
                    break;
                }
            }

            if (ndir != -1)
            {
                // The cell is at border.
                // Walk around the contour to find all the neighbours.
                walkContour(x, y, i, ndir, layer, srcReg, reg.connections);
            }
        }
    }

    // Remove too small regions.
    dtIntArray stack(32);
    dtIntArray trace(32);
    for (int i = 0; i < nreg; ++i)
    {
        dtLayerRegion& reg = regions[i];
        if (reg.id == 0)
            continue;
        if (reg.cellCount == 0)
            continue;
        if (reg.visited)
            continue;

        // Count the total size of all the connected regions.
        // Also keep track of the regions connects to a tile border.
        bool connectsToBorder = false;
        int cellCount = 0;
        stack.resize(0);
        trace.resize(0);

        reg.visited = true;
        stack.push(i);

        while (stack.size())
        {
            // Pop
            int ri = stack.pop();

            dtLayerRegion& creg = regions[ri];

            connectsToBorder |= creg.border;
            cellCount += creg.cellCount;
            trace.push(ri);

            for (int j = 0; j < creg.connections.size(); ++j)
            {
                dtLayerRegion& neireg = regions[creg.connections[j]];
                if (neireg.visited)
                    continue;
                if (neireg.id == 0)
                    continue;
                // Visit
                stack.push(neireg.id);
                neireg.visited = true;
            }
        }

        // If the accumulated regions size is too small, remove it.
        // Do not remove areas which connect to tile borders
        // as their size cannot be estimated correctly and removing them
        // can potentially remove necessary areas.
        if (cellCount < minRegionArea && !connectsToBorder)
        {
            // Kill all visited regions.
            for (int j = 0; j < trace.size(); ++j)
            {
                regions[trace[j]].cellCount = 0;
                regions[trace[j]].id = 0;
            }
        }
    }

    // Merge too small regions to neighbour regions.
    int mergeCount = 0 ;
    do
    {
        mergeCount = 0;
        for (int i = 0; i < nreg; ++i)
        {
            dtLayerRegion& reg = regions[i];
            if (reg.id == 0)
                continue;
            if (reg.cellCount == 0)
                continue;

            // Check to see if the region should be merged.
            if (reg.cellCount > mergeRegionSize && reg.border)
                continue;

            // Small region with more than 1 connection.
            // Or region which is not connected to a border at all.
            // Find smallest neighbour region that connects to this one.
            int smallest = 0xfffffff;
            unsigned short mergeId = reg.id;
            for (int j = 0; j < reg.connections.size(); ++j)
            {
                dtLayerRegion& mreg = regions[reg.connections[j]];
                if (mreg.id == 0) continue;
                if (mreg.cellCount < smallest &&
                        canMergeWithRegion(reg, mreg) &&
                        canMergeWithRegion(mreg, reg))
                {
                    smallest = mreg.cellCount;
                    mergeId = mreg.id;
                }
            }
            // Found new id.
            if (mergeId != reg.id)
            {
                unsigned short oldId = reg.id;
                dtLayerRegion& target = regions[mergeId];

                // Merge neighbours.
                if (mergeRegions(target, reg))
                {
                    // Fixup regions pointing to current region.
                    for (int j = 0; j < nreg; ++j)
                    {
                        if (regions[j].id == 0) continue;
                        // If another region was already merged into current region
                        // change the nid of the previous region too.
                        if (regions[j].id == oldId)
                            regions[j].id = mergeId;
                        // Replace the current region with the new one if the
                        // current regions is neighbour.
                        replaceNeighbour(regions[j], oldId, mergeId);
                    }
                    mergeCount++;
                }
            }
        }
    }
    while (mergeCount > 0);

    // Compress region Ids.
    for (int i = 0; i < nreg; ++i)
    {
        regions[i].remap = false;
        if (regions[i].id == DT_TILECACHE_NULL_AREA) continue;       // Skip nil regions.
        regions[i].remap = true;
    }

    unsigned short regIdGen = 0;
    for (int i = 0; i < nreg; ++i)
    {
        if (!regions[i].remap)
            continue;
        unsigned short oldId = regions[i].id;
        unsigned short newId = ++regIdGen;
        for (int j = i; j < nreg; ++j)
        {
            if (regions[j].id == oldId)
            {
                regions[j].id = newId;
                regions[j].remap = false;
            }
        }
    }
    maxRegionId = regIdGen;

    // Remap regions.
    for (int i = w*h-1; i >= 0; i--)
    {
        srcReg[i] = regions[srcReg[i]].id;
    }

    for (int i = 0; i < nreg; ++i)
        regions[i].~dtLayerRegion();

    return DT_SUCCESS;
}
Beispiel #5
0
  void RegionMerger::initialApproximateMerge(){

    // const int batchSize=40;
    const int initialStop=400;


    int batchnr=0;

    while((int)regionList.size() > initialStop){

//         cout << "beginning batch of initialApproximateMerge" << endl;
//         cout <<"regionCount="<<regionList.size() << endl;
      
      set<int> region;
      set<int> neighbours;
      set<regionDiff> joins;
      
      int batchSize=(regionList.size()-numberOfRegions)/2;
      //int batchSize=500;

      const int l=regionList.size();
	vector<int> labelsInRL;
	map<int,Region>::iterator rit;

	for(rit=regionList.begin();rit!=regionList.end();rit++)
	  labelsInRL.push_back(rit->first);

 // 	cout << labelsInRL.size() << " labels collected:( l=" << l<<")"<<endl;

//  	for(size_t i=0;i<labelsInRL.size();i++)
//  	  cout<<labelsInRL[i]<<endl;
	  

	
      for(int i=0;i<batchSize;i++){
	int j;

	int r=random(l-1);

	//cout << "r="<<r<<endl;

	j=labelsInRL[r];
	if(region.count(j)||neighbours.count(j)) continue;

	//cout << "region set: "<<formVirtualSegmentLabel(region)<<endl;
	//cout << "neighbours: "<<formVirtualSegmentLabel(neighbours)<<endl;

	region.insert(j);

	//char jstr[80];
	//sprintf(jstr,"%d",j);

	//if(regionList.count(j)==0) 
	//  throw string("accepted region ")+jstr+ " not in regionlist";

	const set<int> &nbr=regionList[j].nList;

	//cout << "accepted region "<<j<<" w/ neighbours " << endl
	//     <<"  "<< formVirtualSegmentLabel(nbr)<<endl;

	neighbours.insert(nbr.begin(),nbr.end());
	regionDiff tmp;
	tmp.r1=j;
	tmp.r2=findClosest(j);

	//cout << "closest region: "<<tmp.r2<<endl;
	tmp.dist=regionList[j].count*regionDist(tmp.r1,tmp.r2);
	tmp.dist=regionDist(tmp.r1,tmp.r2);
	joins.insert(tmp);
      }
      
      // cout <<"joins.size()="<<joins.size()<<endl;

      // sort(joins.begin(),joins.end());
      int i=0;
      map<int,int> joinedTo;
      int njoins=joins.size()/2; // arbitrary choice, quite aggressive
      if(njoins<1) njoins=1;

      for(set<regionDiff>::iterator it=joins.begin();i<njoins;
	  i++,it++){
	regionDiff d=*it;
	//cout << "i= "<<i<<" dist="<<it->dist<<endl;
	while(joinedTo.count(d.r1)) d.r1=joinedTo[d.r1];
	while(joinedTo.count(d.r2)) d.r2=joinedTo[d.r2];

	if(d.r1==d.r2) continue;

	mergeRegions(d.r1,d.r2,full_update);
	//	if(regionList.size() != countRegions()){
	//  cout << "batch nr " << batchnr << endl;
	//  cout << "joined regions "<<d.r1<<" and "<<d.r2<<endl;
	//  cout << "regionList.size()="<<regionList.size()<<" (real="<<countRegions()
	//     << ") -> batchSize="<<batchSize<<endl;
	//}

	if(d.r1<d.r2) joinedTo[d.r2]=d.r1;
	else joinedTo[d.r1]=d.r2;
      }  
      batchnr++;
    }

  }
Beispiel #6
0
  void RegionMerger::mergeTopRegions(){
    
    //regionDiff d=queue.top();
    //queue.pop();

    pop_heap(queue_vector.begin(),queue_vector.end());
    regionDiff d=queue_vector.back();
    queue_vector.pop_back();

    if(regionList.count(d.r1)==0 ||regionList.count(d.r2)==0){
      // cout << "popped inexistent merge" << endl;
      return;
    }

    if(d.r1>d.r2){
      int tmp=d.r1;
      d.r1=d.r2;
      d.r2=tmp;
    }
    
    Region *r1=&(regionList[d.r1]);
    Region *r2=&(regionList[d.r2]);

    if(d.timestamp < r1->timestamp || d.timestamp < r2->timestamp) return;

    currentTime++;

    int i=d.r1,i2=d.r2;

    //     cout << "Merging regions " << d.r1 <<" and " << d.r2 
    //       << " w\\ d=" << d.dist << endl;

//     cout << "Feature vectors:" << endl << " r1: ";
//     Feature::printFeatureVector(cout,r1->fV);
//     cout << endl << " r2: ";
//     Feature::printFeatureVector(cout,r2->fV);


//     cout << "Neighbours of r1: " << endl;
    set<int>::iterator it;

  //   for(it=r1->nList.begin(); it != r1->nList.end(); it++){
//       if(regionList[*it].count){
// 	cout << "     #"<<*it<<" (size "<<regionList[*it].count<<"):";
//       Feature::printFeatureVector(cout,regionList[*it].fV);
//       cout << endl;
//       }
//     }

//     cout << "Neighbours of r2: " << endl;
//     for(it=r2->nList.begin(); it != r2->nList.end(); it++){
//       if(regionList[*it].count){
// 	cout << "     #"<<*it<<" (size "<<regionList[*it].count<<"):";
// 	Feature::printFeatureVector(cout,regionList[*it].fV);
// 	cout << endl;
//       }
//     }

    mergeRegions(d.r1,d.r2,full_update);

    // now pointer r2 becomes invalid

    for(it=r1->nList.begin(); it != r1->nList.end(); it++){
      Region *r=&(regionList[*it]);
      bool otherBefore = (r->closestNeighbour != i && r->closestNeighbour != i2); 
      r->closestNeighbour=findClosest(*it);
      if(r->closestNeighbour != i && otherBefore) continue; 
      // other relevant merges remain in the queue

      regionDiff d;
      d.timestamp=currentTime;
      d.r1=*it;
      d.r2=r->closestNeighbour;
      d.dist = -regionDist(d.r1,d.r2);
      //queue.push(d);
      //    cout << "pushed merge: " << d.print() << endl;
      queue_vector.push_back(d);
      push_heap(queue_vector.begin(),queue_vector.end());

    }
    if(r1->nList.size()){

      r1->closestNeighbour=findClosest(i);
    
      regionDiff dn;
      dn.timestamp=currentTime;
      dn.r1=i;
      dn.r2=r1->closestNeighbour;
      dn.dist = -regionDist(dn.r1,dn.r2);
      //queue.push(d);
      queue_vector.push_back(dn);
      //cout << "pushed merge: " << dn.print() << endl;
      push_heap(queue_vector.begin(),queue_vector.end());
      
      r1->timestamp=currentTime;
      //r2->timestamp=currentTime;
    }
    // dumpRegionList();
    
    
  }
Beispiel #7
0
  bool RegionMerger::joinSmallRegions()
  {
    
    // first look for small regions that have only one neighbour
    int nregions=0;
    // dumpRegionList();
    map<int,Region>::iterator rit=regionList.begin();



    bool first=true;

    while(rit!=regionList.end()&&(int)regionList.size()>numberOfRegions){
      if((int)rit->second.count<=sizeThreshold ){
	nregions++;
	if((int)rit->second.nList.size()==1){
	  
	  // some tricks to avoid iterators going invalid
	  
	  if(first){
	    mergeRegions(rit->first,*rit->second.nList.begin(),no_update);
	    rit=regionList.begin();
	    continue;
	  }
	  else{
	    const map<int,Region>::iterator ritwas=rit;
	    rit--;
	    mergeRegions(ritwas->first,
			 *ritwas->second.nList.begin(),no_update);
	  }
	}
      }
      rit++;
      first=false;
    } // while    

    if(Verbose()>1){
      cout << nregions <<" small regions." << endl;
      cout << "regions w/ one neighbour joined." << endl;
      cout << "region count now " << regionList.size() << endl;
    }

    // then merge all small regions to their closest neighbours
  
      int smallmerges=0;

      bool approx_update=!useAveraging;

      bool fromFirst=false;

      rit=regionList.begin();
      while(rit!=regionList.end()&&(int)regionList.size()>numberOfRegions){
	  while((int)rit->second.count<=sizeThreshold){

	    const int n=findClosest(rit->first);
	    bool isInvalidated= rit->first > n;

	    fromFirst= isInvalidated && (rit==regionList.begin());
	    const map<int,Region>::iterator ritwas=rit;
	    if(isInvalidated) rit--;
	    mergeRegions(ritwas->first,n,
			 approx_update?choose_larger:full_update);
	    smallmerges++;
	    if(Verbose()>1 && smallmerges%100==0)
	      cout << smallmerges <<" small regions merged." << endl;
	    if(isInvalidated) break;
	  } // while

	if(fromFirst){
	  rit=regionList.begin();
	  fromFirst=false;
	}
	else{
	  rit++;
	}

      } // while
	
      if(approx_update){
	// all merges done, update remaining feature vectors
	for(rit=regionList.begin();rit!=regionList.end();rit++)
	    updateFeatureValues(rit->first);
      }

      // cout << "small regions joined" << endl;

      return true;
    
    }