std::vector<TRI_doc_mptr_copy_t> TRI_LookupEdgesDocumentCollection (
    TRI_document_collection_t* document,
    TRI_edge_direction_e direction,
    TRI_voc_cid_t cid,
    TRI_voc_key_t const key) {
    // search criteria
    TRI_edge_header_t entry(cid, key);

    // initialize the result vector
    std::vector<TRI_doc_mptr_copy_t> result;

    auto edgeIndex = document->edgeIndex();

    if (edgeIndex == nullptr) {
        LOG_ERROR("collection does not have an edges index");
        return result;
    }

    if (direction == TRI_EDGE_IN) {
        // get all edges with a matching IN vertex
        FindEdges(TRI_EDGE_IN, edgeIndex, result, &entry, 1);
    }
    else if (direction == TRI_EDGE_OUT) {
        // get all edges with a matching OUT vertex
        FindEdges(TRI_EDGE_OUT, edgeIndex, result, &entry, 1);
    }
    else if (direction == TRI_EDGE_ANY) {
        // get all edges with a matching IN vertex
        FindEdges(TRI_EDGE_IN, edgeIndex, result, &entry, 1);
        // add all non-reflexive edges with a matching OUT vertex
        FindEdges(TRI_EDGE_OUT, edgeIndex, result, &entry, 3);
    }

    return result;
}
Example #2
0
CEdge* HVertex::GetFirstEdge()
{
	if (m_edges.size()==0)FindEdges();
	if (m_edges.size()==0) return NULL;
	m_edgeIt = m_edges.begin();
	return *m_edgeIt;
}
void HierarchicalPathfinder::Recompute(Grid<NavcellData>* grid,
	const std::map<std::string, pass_class_t>& nonPathfindingPassClassMasks,
	const std::map<std::string, pass_class_t>& pathfindingPassClassMasks)
{
	PROFILE3("Hierarchical Recompute");

	m_PassClassMasks = pathfindingPassClassMasks;

	std::map<std::string, pass_class_t> allPassClasses = m_PassClassMasks;
	allPassClasses.insert(nonPathfindingPassClassMasks.begin(), nonPathfindingPassClassMasks.end());

	m_W = grid->m_W;
	m_H = grid->m_H;

	// Divide grid into chunks with round-to-positive-infinity
	m_ChunksW = (grid->m_W + CHUNK_SIZE - 1) / CHUNK_SIZE;
	m_ChunksH = (grid->m_H + CHUNK_SIZE - 1) / CHUNK_SIZE;

	ENSURE(m_ChunksW < 256 && m_ChunksH < 256); // else the u8 Chunk::m_ChunkI will overflow

	m_Chunks.clear();
	m_Edges.clear();

	for (auto& passClassMask : allPassClasses)
	{
		pass_class_t passClass = passClassMask.second;

		// Compute the regions within each chunk
		m_Chunks[passClass].resize(m_ChunksW*m_ChunksH);
		for (int cj = 0; cj < m_ChunksH; ++cj)
		{
			for (int ci = 0; ci < m_ChunksW; ++ci)
			{
				m_Chunks[passClass].at(cj*m_ChunksW + ci).InitRegions(ci, cj, grid, passClass);
			}
		}

		// Construct the search graph over the regions

		EdgesMap& edges = m_Edges[passClass];

		for (int cj = 0; cj < m_ChunksH; ++cj)
		{
			for (int ci = 0; ci < m_ChunksW; ++ci)
			{
				FindEdges(ci, cj, passClass, edges);
			}
		}
	}

	if (m_DebugOverlay)
	{
		PROFILE("debug overlay");
		m_DebugOverlayLines.clear();
		AddDebugEdges(GetPassabilityClass("default"));
	}
}
Example #4
0
TRI_vector_pointer_t TRI_LookupEdgesDocumentCollection (TRI_document_collection_t* document,
                                                        TRI_edge_direction_e direction,
                                                        TRI_voc_cid_t cid,
                                                        TRI_voc_key_t key) {
  TRI_vector_pointer_t result;
  TRI_edge_header_t entry;
  TRI_multi_pointer_t* edgesIndex;

  // search criteria
  entry._mptr = NULL;
  entry._cid = cid;
  entry._searchKey._key = key;

  // initialise the result vector
  TRI_InitVectorPointer(&result, TRI_UNKNOWN_MEM_ZONE);

  edgesIndex = FindEdgesIndex(document);
  if (edgesIndex == NULL) {
    LOG_ERROR("collection does not have an edges index");
    return result;
  }

  if (direction == TRI_EDGE_IN) {
    // get all edges with a matching IN vertex
    FindEdges(TRI_EDGE_IN, edgesIndex, &result, &entry, 1);
  }
  else if (direction == TRI_EDGE_OUT) {
    // get all edges with a matching OUT vertex
    FindEdges(TRI_EDGE_OUT, edgesIndex, &result, &entry, 1);
  }
  else if (direction == TRI_EDGE_ANY) {
    // get all edges with a matching IN vertex
    FindEdges(TRI_EDGE_IN, edgesIndex, &result, &entry, 1);
    // add all non-reflexive edges with a matching OUT vertex
    FindEdges(TRI_EDGE_OUT, edgesIndex, &result, &entry, 3);
  }

  return result;
}
Example #5
0
void HierarchicalPathfinder::Update(Grid<NavcellData>* grid, const Grid<u8>& dirtinessGrid)
{
	PROFILE3("Hierarchical Update");

	std::vector<std::pair<int, int> > processedChunks;
	for (int j = 0; j < dirtinessGrid.m_H; ++j)
	{
		for (int i = 0; i < dirtinessGrid.m_W; ++i)
		{
			if (!dirtinessGrid.get(i, j))
				continue;

			std::pair<int, int> chunkID(i / CHUNK_SIZE, j / CHUNK_SIZE);

			for (auto& passClassMask : m_PassClassMasks)
			{
				pass_class_t passClass = passClassMask.second;
				Chunk& a = m_Chunks[passClass].at(chunkID.second*m_ChunksW + chunkID.first);
				if (std::find(processedChunks.begin(), processedChunks.end(), chunkID) == processedChunks.end())
				{
					processedChunks.push_back(chunkID);
					a.InitRegions(chunkID.first, chunkID.second, grid, passClass);
				}
			}
		}
	}

	// TODO: Also be clever with edges
	m_Edges.clear();
	for (auto& passClassMask : m_PassClassMasks)
	{
		pass_class_t passClass = passClassMask.second;
		EdgesMap& edges = m_Edges[passClass];

		for (int cj = 0; cj < m_ChunksH; ++cj)
		{
			for (int ci = 0; ci < m_ChunksW; ++ci)
			{
				FindEdges(ci, cj, passClass, edges);
			}
		}
	}

	if (m_DebugOverlay)
	{
		PROFILE("debug overlay");
		m_DebugOverlayLines.clear();
		AddDebugEdges(GetPassabilityClass("default"));
	}
}
Example #6
0
void plInterMeshSmooth::SmoothNormals(hsTArray<plSpanHandle>& sets)
{
    hsTArray<uint16_t>* shareVtx = new hsTArray<uint16_t>[sets.GetCount()];
    hsTArray<uint16_t>* edgeVerts = new hsTArray<uint16_t>[sets.GetCount()];
    FindEdges(sets, edgeVerts);

    int i;
    for( i = 0; i < sets.GetCount()-1; i++ )
    {
        int j;
        for( j = edgeVerts[i].GetCount()-1; j >= 0; --j )
        {
            hsPoint3 pos = GetPosition(sets[i], edgeVerts[i][j]);
            hsVector3 normAccum = GetNormal(sets[i], edgeVerts[i][j]);;

            shareVtx[i].Append(edgeVerts[i][j]);

            int k;
            for( k = i+1; k < sets.GetCount(); k++ )
            {
                FindSharedVerts(pos, sets[k], edgeVerts[k], shareVtx[k], normAccum);
            }

            normAccum.Normalize();
            GetNormal(sets[i], edgeVerts[i][j]) = normAccum;

            for( k = i+1; k < sets.GetCount(); k++ )
            {
                SetNormals(sets[k], shareVtx[k], normAccum);
            }

            // Now remove all the shared verts (which we just processed)
            // from edgeVerts so we don't process them again.
            for( k = i; k < sets.GetCount(); k++ )
            {
                int m;
                for( m = 0; m < shareVtx[k].GetCount(); m++ )
                {
                    int idx = edgeVerts[k].Find(shareVtx[k][m]);
                    hsAssert(idx != edgeVerts[k].kMissingIndex, "Lost vertex between find and remove");
                    edgeVerts[k].Remove(idx);
                }
                shareVtx[k].SetCount(0);
            }
        }
    }

    delete [] shareVtx;
    delete [] edgeVerts;
}
Example #7
0
void plInterMeshSmooth::FindEdges(hsTArray<plSpanHandle>& sets, hsTArray<uint16_t>* edgeVerts)
{
    int i;
    for( i = 0; i < sets.GetCount(); i++ )
    {
        const plSpan* span = sets[i].fDrawable->GetSpan(sets[i].fSpanIdx);
        if( !(span->fTypeMask & plSpan::kIcicleSpan) )
            continue;

        uint32_t nTris = sets[i].fDrawable->CvtGetNumTris(sets[i].fSpanIdx);
        uint16_t* idxList = sets[i].fDrawable->CvtGetIndexList(sets[i].fSpanIdx);
        uint32_t maxVertIdx = sets[i].fDrawable->CvtGetNumVerts(sets[i].fSpanIdx)-1;

        FindEdges(maxVertIdx, nTris, idxList, edgeVerts[i]);
    }
}
void HierarchicalPathfinder::Update(Grid<NavcellData>* grid, const Grid<u8>& dirtinessGrid)
{
	PROFILE3("Hierarchical Update");

	for (int cj = 0; cj <  m_ChunksH; ++cj)
	{
		for (int ci = 0; ci < m_ChunksW; ++ci)
		{
			if (!IsChunkDirty(ci, cj, dirtinessGrid))
				continue;
			for (const std::pair<std::string, pass_class_t>& passClassMask : m_PassClassMasks)
			{
				pass_class_t passClass = passClassMask.second;
				Chunk& a = m_Chunks[passClass].at(ci + cj*m_ChunksW);
				a.InitRegions(ci, cj, grid, passClass);
			}
		}
	}

	// TODO: Also be clever with edges
	m_Edges.clear();
	for (const std::pair<std::string, pass_class_t>& passClassMask : m_PassClassMasks)
	{
		pass_class_t passClass = passClassMask.second;
		EdgesMap& edges = m_Edges[passClass];

		for (int cj = 0; cj < m_ChunksH; ++cj)
		{
			for (int ci = 0; ci < m_ChunksW; ++ci)
			{
				FindEdges(ci, cj, passClass, edges);
			}
		}
	}

	if (m_DebugOverlay)
	{
		PROFILE("debug overlay");
		m_DebugOverlayLines.clear();
		AddDebugEdges(GetPassabilityClass("default"));
	}
}
Example #9
0
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//
void Next()
{
  GetProjection(event, event);
  
  FindEdges(); 

  if( (start[1]-start[0])> MinStartDist ) // limit the burst distance
    {
      GetAmpSignals();
      
      GetPMTSignals();
      
      GetShpSignals();

      if( !(event%100) )
	{
	  DrawAll();  
	  DrawDistributions();
	  PrintAll();
	  printf("event: %i\n", event);
	}  
    }
  event++;

  if( event == event_lastt )
    {
      ftimer.Stop();
                  
      FitProfiles();
      
      PrintAll();

      DrawAll();  

      DrawDistributions();

      WriteAll();
      
      gSystem->Exit(1);
    }
}
Example #10
0
/*************
 * DESCRIPTION:   read the polygons
 * INPUT:         data     handler data
 *                cn       iff context node
 *                actor    actor
 * OUTPUT:        error string
 *************/
static char *ReadPolygons(HANDLER_DATA *data, struct ContextNode *cn, ACTOR *actor)
{
	ULONG count, edgecount, i,j,k,l;
	WORD *polybuffer = NULL, *p;
	LINK_EDGE *edges;
	LINK_MESH *faces;
	OBJECT *obj;
	VECTOR ox,oy,oz, axis_pos,axis_size;
	SURF_DATA *cursurf;

	SetVector(&axis_pos, 0.f, 0.f, 0.f);
	SetVector(&ox, 1.f, 0.f, 0.f);
	SetVector(&oy, 0.f, 1.f, 0.f);
	SetVector(&oz, 0.f, 0.f, 1.f);
	SetVector(&axis_size, 1.f, 1.f, 1.f);

	// Allocate Memory for whole chunk (the last word is the surface index for this polygon)
	count = cn->cn_Size/2 - 1;
	polybuffer = ALLOCMEM(WORD, count);
	if (!polybuffer)
		return errors[ERR_MEM];

	// Read polygons
	if(!ReadWord(data->iff, polybuffer, count))
	{
		FREEMEM(polybuffer);
		return errors[ERR_LWOBFILE];
	}

	// go through buffer and look how many edges and faces we need
	i = 0;
	while(i < count)
	{
		cursurf = &data->surfaces[abs(polybuffer[i+polybuffer[i]+1])-1];
		switch(polybuffer[i])
		{
			case 1:
			case 2:
				break;
			case 3:  // triangle
				cursurf->facecount++;
				cursurf->edgecount += 3;
				break;
			case 4:  //rectangle
				cursurf->facecount += 2;
				cursurf->edgecount += 5;
				break;
			default: // polygon
				cursurf->facecount += polybuffer[i] - 2;
				cursurf->edgecount += (polybuffer[i] - 2) * 2 + 1;
				break;
		}
		p = &polybuffer[i+1];
		for(j=0; j<polybuffer[i]; j++)
		{
			if(cursurf->nobound)
			{
				cursurf->lowbound = cursurf->highbound = data->points[*p];
				cursurf->nobound = FALSE;
			}
			else
			{
				if(data->points[*p].x < cursurf->lowbound.x)
					cursurf->lowbound.x = data->points[*p].x;
				if(data->points[*p].y < cursurf->lowbound.y)
					cursurf->lowbound.y = data->points[*p].y;
				if(data->points[*p].z < cursurf->lowbound.z)
					cursurf->lowbound.z = data->points[*p].z;

				if(data->points[*p].x > cursurf->highbound.x)
					cursurf->highbound.x = data->points[*p].x;
				if(data->points[*p].y > cursurf->highbound.y)
					cursurf->highbound.y = data->points[*p].y;
				if(data->points[*p].z > cursurf->highbound.z)
					cursurf->highbound.z = data->points[*p].z;
			}
			p++;
		}
		i += polybuffer[i] + 1;
		// if surface number < 0 then get detail polygons
		if (polybuffer[i] < 0)
		{
			// jump over amount of detail polygons
			i++;
		}
		i++;
	}

	// for each surface go through the polygons and create a single object
	for(j=0; j<data->surfcount; j++)
	{
		data->link->ObjectBegin(data->rc);
		cursurf = &data->surfaces[j];
		if(cursurf->edgecount && cursurf->facecount)
		{
			// Allocate memory for edges
			edges = ALLOCMEM(LINK_EDGE, cursurf->edgecount);
			if (!edges)
			{
				FREEMEM(polybuffer);
				FreeBuffers(data);
				return errors[ERR_MEM];
			}
			// Allocate memory for faces
			faces = ALLOCMEM(LINK_MESH, cursurf->facecount);
			if (!faces)
			{
				FREEMEM(edges);
				FREEMEM(polybuffer);
				FreeBuffers(data);
				return errors[ERR_MEM];
			}

			// and again, go through buffer and now create edges, create only
			// one edge between two points
			i = 0;
			k = 0;   // current face
			edgecount = 0;
			while(i < count)
			{
				if(j == (ULONG)abs(polybuffer[i+polybuffer[i]+1])-1)
				{
					switch(polybuffer[i])
					{
						case 1:
						case 2:
							break;
						case 3:  // triangle
							// search for edge, and create one if no found
							FindEdges(&faces[k], &edgecount, polybuffer[i+1], polybuffer[i+2], polybuffer[i+3], edges);
							k++;
							break;
						case 4:  // rectangle
							// split rectangle in two triangles
							// search for edge, and create one if no found
							FindEdges(&faces[k], &edgecount, polybuffer[i+1], polybuffer[i+2], polybuffer[i+3], edges);
							k++;

							FindEdges(&faces[k], &edgecount, polybuffer[i+3], polybuffer[i+4], polybuffer[i+1], edges);
							k++;
							break;
						default: // polygon
							for(l = 0; l < (ULONG)polybuffer[i]-2; l++)
							{
								FindEdges(&faces[k], &edgecount, polybuffer[i+1], polybuffer[i+l+2], polybuffer[i+l+3], edges);
								k++;
							}
							break;
					}
				}

				i += polybuffer[i] + 1;
				// if surface number < 0 then get detail polygons
				if (polybuffer[i] < 0)
				{
					// jump over amount of detail polygons
					i++;
				}
				i++;
			}

			if(data->link->type == LINK_SCENARIO)
			{
				SetVector(&axis_pos,
					(cursurf->lowbound.x + cursurf->highbound.x) * .5f,
					(cursurf->lowbound.y + cursurf->highbound.y) * .5f,
					(cursurf->lowbound.z + cursurf->highbound.z) * .5f);
				SetVector(&axis_size,
					(cursurf->highbound.x - cursurf->lowbound.x) * .5f,
					(cursurf->highbound.y - cursurf->lowbound.y) * .5f,
					(cursurf->highbound.z - cursurf->lowbound.z) * .5f);

				obj = data->link->MeshCreate(data->rc);
				if(!obj)
					return errors[ERR_MEM];

				if((cursurf->object_count & 0xF) == 0)
				{
					OBJECT **objects;

					objects = new OBJECT*[cursurf->object_count+16];
					if(!objects)
						return errors[ERR_MEM];

					if(cursurf->object_count)
						memcpy(objects, cursurf->objects, cursurf->object_count*sizeof(OBJECT*));

					if(cursurf->objects)
						delete cursurf->objects;

					cursurf->objects = objects;
				}

				cursurf->objects[cursurf->object_count] = obj;
				cursurf->object_count++;

				data->link->ObjectAxis(data->rc, obj, &axis_pos, &ox,&oy,&oz, &axis_size);
				if(cursurf->name)
					data->link->ObjectName(data->rc, obj, cursurf->name);

				if(!data->link->MeshAddScenario(data->rc, obj,
					data->points, data->pointcount,
					edges, cursurf->edgecount,
					faces, cursurf->facecount,
					&data->size,
					FALSE))
				{
					FREEMEM(edges);
					FREEMEM(faces);
					FREEMEM(polybuffer);
					return errors[ERR_MEM];
				}
				data->link->ObjectSurface(data->rc, obj, cursurf->surface);
			}
			else
			{
				if(!data->link->MeshAddRenderer(data->rc, cursurf->surface, NULL, actor,
					data->points, data->pointcount,
					edges, cursurf->edgecount,
					faces, cursurf->facecount,
					&data->pos, &data->ox, &data->oy, &data->oz, &data->size,
					FALSE))
				{
					FREEMEM(edges);
					FREEMEM(faces);
					FREEMEM(polybuffer);
					return errors[ERR_MEM];
				}
			}
			FREEMEM(edges);
			FREEMEM(faces);
		}
		else
		{
			if(data->link->type == LINK_SCENARIO)
			{
				// Scenario needs even empty meshes to create the axis
				obj = data->link->MeshCreate(data->rc);
				if(!obj)
					return errors[ERR_MEM];

				data->link->ObjectAxis(data->rc, obj, &axis_pos, &ox,&oy,&oz, &axis_size);
				if(cursurf->name)
					data->link->ObjectName(data->rc, obj, cursurf->name);
				data->link->ObjectSurface(data->rc, obj, cursurf->surface);
			}
		}
		data->link->ObjectEnd(data->rc);
		if(data->SetProgress)
			data->SetProgress(data->rc, ((float)data->size_done + (float)(cn->cn_Size*j)/(float)data->surfcount)/(float)data->filesize);
	}

	// free polygonbuffer
	if(polybuffer)
		FREEMEM(polybuffer);

	return NULL;
}
const boost::shared_ptr<ribi::cmap::ConceptMap> ribi::cmap::QtRateConceptMap::CreateSubConceptMap(QtNode * const item)
{
  assert(item);
  //Collect all nodes first
  const std::vector<QtEdge*> qtedges = FindEdges(item);
  std::vector<boost::shared_ptr<ribi::cmap::Node> > nodes;
  //assert(focal_concept);
  const boost::shared_ptr<ribi::cmap::Node> focal_node = item->GetNode(); //FIX?
  assert(focal_node);
  nodes.push_back(focal_node);

  assert(nodes[0]->GetConcept() == item->GetNode()->GetConcept());

  std::vector<boost::shared_ptr<ribi::cmap::Edge> > edges;

  const int sz = static_cast<int>(qtedges.size());
  for (int i=0; i!=sz; ++i)
  {
    QtEdge* const qtedge = qtedges[i];
    assert(qtedge);
    assert(qtedge->GetFrom());
    assert(qtedge->GetTo());
    assert(qtedge->GetArrow());
    assert(qtedge->GetArrow()->GetFromItem());
    assert(dynamic_cast<const QtNode*>(qtedge->GetArrow()->GetFromItem()));
    assert(dynamic_cast<const QtNode*>(qtedge->GetArrow()->GetFromItem())->GetNode());
    assert(dynamic_cast<const QtNode*>(qtedge->GetArrow()->GetFromItem())->GetNode()->GetConcept());
    assert(dynamic_cast<const QtNode*>(qtedge->GetArrow()->GetToItem()));
    assert(dynamic_cast<const QtNode*>(qtedge->GetArrow()->GetToItem())->GetNode());
    assert(dynamic_cast<const QtNode*>(qtedge->GetArrow()->GetToItem())->GetNode()->GetConcept());
    const boost::shared_ptr<ribi::cmap::Node> other_node
      = qtedge->GetFrom()->GetNode() == focal_node
      ? qtedge->GetTo()->GetNode()
      : qtedge->GetFrom()->GetNode();
    assert(other_node);
    assert(other_node != focal_node);
    nodes.push_back(other_node);
    assert(qtedge);
    assert(qtedge->GetEdge());
    const boost::shared_ptr<Edge> edge(cmap::EdgeFactory::Create(
      qtedge->GetEdge()->GetConcept(),
      qtedge->GetEdge()->GetX(),
      qtedge->GetEdge()->GetY(),
      focal_node,
      qtedge->GetEdge()->HasTailArrow(),
      other_node,
      qtedge->GetEdge()->HasHeadArrow()
      )
    );
    assert(edge);
    edges.push_back(edge);
  }
  assert(ConceptMap::CanConstruct(nodes,edges));
  const boost::shared_ptr<ConceptMap> concept_map(cmap::ConceptMapFactory::Create(nodes,edges));
  assert(concept_map);
  assert(focal_node == concept_map->GetFocalNode());

  assert(concept_map->GetFocalNode());
  assert(concept_map->GetFocalNode()->GetConcept());
  assert(concept_map->GetFocalNode()->GetConcept().get() == item->GetNode()->GetConcept().get()
    && "Should not be a deep copy, otherwise item will not be changed");

  return concept_map;
}
Example #12
0
void TR()
{
#if defined(DEBUG) && defined(_MSC_VER)
    _CrtSetDbgFlag(0);	// too expensive
#endif

    const char *HitFileName = RequiredValueOpt("tr");
    const char *OutFileName = RequiredValueOpt("out");
    const char *CandFileName = ValueOpt("cand");

    const char *strMinTrSpacing = ValueOpt("mintrspacing");
    const char *strMaxTrSpacing = ValueOpt("maxtrspacing");
    const char *strMinTrLength = ValueOpt("mintrlength");
    const char *strMaxTrLength = ValueOpt("minspacingratio");
    const char *strMinFam = ValueOpt("minfam");
    const char *strMinHitRatio = ValueOpt("minhitratio");
    const char *strMinDistPairs = ValueOpt("mindistpairs");

    if (0 != strMinTrSpacing)
        MIN_LENGTH_LINE = atoi(strMinTrSpacing);
    if (0 != strMaxTrSpacing)
        MAX_LENGTH_LINE = atoi(strMaxTrSpacing);
    if (0 != strMinTrLength)
        MIN_LENGTH_LTR = atoi(strMinTrLength);
    if (0 != strMaxTrLength)
        MAX_LENGTH_LTR = atoi(strMaxTrLength);
    if (0 != strMinFam)
        MIN_FAM_SIZE = atoi(strMinFam);
    if (0 != strMinHitRatio)
        MIN_HIT_LENGTH_RATIO = atoi(strMinHitRatio);
    if (0 != strMinDistPairs)
        MIN_DIST_EDGE = atoi(strMinDistPairs);

    FILE *fHit = OpenStdioFile(HitFileName, FILEIO_MODE_ReadOnly);

    ProgressStart("Index hits");
    GLIX HitGlix;
    HitGlix.Init();
    HitGlix.FromGFFFile(fHit);
    HitGlix.MakeGlobalToLocalIndex();
    ProgressDone();

    const int GlobalLength = HitGlix.GetGlobalLength();
    IIX IntervalIndex;
    IntervalIndex.Init(GlobalLength);

    ProgressStart("Find candidate TRs");
    Rewind(fHit);
    GFFRecord Rec;
    while (GetNextGFFRecord(fHit, Rec))
    {
        HitData Hit;
        GFFRecordToHit(HitGlix, Rec, Hit);
        if (IsCandLTR(Hit))
            AddCand(Hit, IntervalIndex);
    }
    ProgressDone();

    Progress("%d candidates", CandCount);

    if (0 != CandFileName)
    {
        ProgressStart("Write candidates");
        FILE *fCand = OpenStdioFile(CandFileName, FILEIO_MODE_WriteOnly);
        WriteCands(fCand, HitGlix);
        ProgressDone();
    }

    ProgressStart("Make graph");
    Rewind(fHit);
    while (GetNextGFFRecord(fHit, Rec))
    {
        HitData Hit;
        GFFRecordToHit(HitGlix, Rec, Hit);
        FindEdges(Hit, HitGlix, IntervalIndex);
    }
    fclose(fHit);
    fHit = 0;

    ProgressDone();

    Progress("%d edges", (int) Edges.size());

    ProgressStart("Find families");
    FamList Fams;
    FindConnectedComponents(Edges, Fams, MIN_FAM_SIZE);
    ProgressDone();

    Progress("%d families", (int) Fams.size());

    FILE *fOut = OpenStdioFile(OutFileName, FILEIO_MODE_WriteOnly);
    WriteOutputFile(fOut, HitGlix, Fams);
}
const boost::shared_ptr<pvdb::ConceptMap> QtPvdbConceptMapRateWidget::CreateSubConceptMap(QtPvdbNodeItem * const item) const
{
  assert(item);
  //Collect all nodes first
  const std::vector<QtPvdbEdgeItem*> qtedges = FindEdges(item);
  std::vector<boost::shared_ptr<pvdb::Node> > nodes;
  //const boost::shared_ptr<pvdb::Concept> focal_concept = pvdb::ConceptFactory::DeepCopy(item->GetConcept());
  //assert(focal_concept);
  const boost::shared_ptr<pvdb::Node> focal_node = item->GetNode(); //FIX?
  //const boost::shared_ptr<pvdb::Node> focal_node = pvdb::NodeFactory::DeepCopy(item->GetNode()); //BUG 2013-01-06
  assert(focal_node);
  nodes.push_back(focal_node);
  assert(nodes[0]->GetConcept() == item->GetNode()->GetConcept());

  std::vector<boost::shared_ptr<pvdb::Edge> > edges;

  const int sz = static_cast<int>(qtedges.size());
  for (int i=0; i!=sz; ++i)
  {
    QtPvdbEdgeItem* const qtedge = qtedges[i];
    assert(qtedge);
    assert(qtedge->GetFrom());
    assert(qtedge->GetTo());
    assert(qtedge->GetArrow());
    assert(qtedge->GetArrow()->GetFromItem());
    assert(dynamic_cast<const QtPvdbNodeItem*>(qtedge->GetArrow()->GetFromItem()));
    assert(dynamic_cast<const QtPvdbNodeItem*>(qtedge->GetArrow()->GetFromItem())->GetNode());
    assert(dynamic_cast<const QtPvdbNodeItem*>(qtedge->GetArrow()->GetFromItem())->GetNode()->GetConcept());
    assert(dynamic_cast<const QtPvdbNodeItem*>(qtedge->GetArrow()->GetToItem()));
    assert(dynamic_cast<const QtPvdbNodeItem*>(qtedge->GetArrow()->GetToItem())->GetNode());
    assert(dynamic_cast<const QtPvdbNodeItem*>(qtedge->GetArrow()->GetToItem())->GetNode()->GetConcept());
    const boost::shared_ptr<const pvdb::Node> other_node
      = qtedge->GetFrom()->GetNode() == focal_node
      ? qtedge->GetTo()->GetNode()
      : qtedge->GetFrom()->GetNode();
    assert(other_node);
    const boost::shared_ptr<pvdb::Node> node = pvdb::NodeFactory::DeepCopy(other_node);
    assert(node);
    nodes.push_back(node);

    const int from_index = qtedge->GetFrom()->GetNode() == focal_node ? 0 : i + 1;
    const int to_index   = qtedge->GetFrom()->GetNode() == focal_node ? i + 1 : 0;
    assert(from_index < static_cast<int>(nodes.size()));
    assert(to_index   < static_cast<int>(nodes.size()));

    //const QtPvdbArrow * arrow = this->FindBuddyArrow(qtedge);
    //assert(arrow);
    assert(qtedge);
    assert(qtedge->GetEdge());
    const boost::shared_ptr<pvdb::Edge> edge(pvdb::EdgeFactory::Create(
      qtedge->GetEdge()->GetConcept(), //Deep copy
      0.0,0.0,
      from_index,
      qtedge->GetEdge()->HasTailArrow(),
      to_index,
      qtedge->GetEdge()->HasHeadArrow()
      )
    );
    assert(edge);
    edges.push_back(edge);
  }
  const boost::shared_ptr<pvdb::ConceptMap> concept_map(pvdb::ConceptMapFactory::Create(nodes,edges));
  assert(concept_map);
  assert(focal_node == concept_map->GetNodes().at(0));

  assert(concept_map->GetNodes().at(0));
  assert(concept_map->GetNodes().at(0)->GetConcept());
  assert(concept_map->GetNodes().at(0)->GetConcept().get() == item->GetNode()->GetConcept().get()
    && "Should not be a deep copy, otherwise item will not be changed");

  return concept_map;
}
BOOL CConvexHullGenerator::Generate(void)
{
	int							iMaxXIndex;
	int							iMinXIndex;
	CHalfSpaceHelper			cHalfSpace;
	int							iFarIndex;
	SFloat3*					psPosition;
	CArrayExtremeTrianglePtr	apcTriangles;
	CExtremeTriangle*			pcTriangle;
	CExtremeTriangle*			pcDeleted;
	SFreeListIterator			sIter;
	CArrayExtremeTrianglePtr	cDeleted;
	CArrayExtremeTrianglePtr	cFixedDeleted;
	int							j;
	SConvexHullHoleEdge			sEdges;
	int							k;
	int							aiIndex[3];
	int							iIndex;
	CExtremeTriangle*			pcSelected;
	CTextFile					cTextFile;
	int							iTriangle;
	float						fMinX;
	float						fMaxX;

	iMaxXIndex = FindMaxX(&fMinX);
	iMinXIndex = FindMinX(&fMaxX);
	iFarIndex = FindFurthestPoint(iMaxXIndex, iMinXIndex);

	if (iFarIndex == -1)
	{
		gcUserError.Set("Could not find a third point generating Convex Hull.");
		return FALSE;
	}

	apcTriangles.Init(2048);

	if (!FindFirstPairTriangles(&apcTriangles, iMaxXIndex, iMinXIndex, iFarIndex))
	{
		gcUserError.Set("Could not find the first triangle pair generating Convex Hull.");
		return FALSE;
	}

	cDeleted.Init(512);
	cFixedDeleted.Init(512);

	for (iTriangle = 0; iTriangle < apcTriangles.NumElements(); iTriangle++)
	{
		pcSelected = *apcTriangles.Get(iTriangle);

		if ((pcSelected == NULL) || (pcSelected->maiVisible.NumElements() == 0))
		{
			continue;
		}

		aiIndex[0] = GetIndex(mpsPoints, iStride, pcSelected->mpsPosition);
		aiIndex[1] = GetIndex(mpsPoints, iStride, pcSelected->mpsPosition1);
		aiIndex[2] = GetIndex(mpsPoints, iStride, pcSelected->mpsPosition2);

		iFarIndex = pcSelected->FindFurthestPoint(mpsPoints, iStride);
		if (iFarIndex == -1)
		{
			gcUserError.Set("Could not find furthest point!");
			return FALSE;
		}

		cDeleted.FakeSetUsedElements(0);  //It's sort of safe to do this.

		psPosition = GetPosition(mpsPoints, iStride, iFarIndex);
		pcTriangle = (CExtremeTriangle*)mcTriangles.StartIteration(&sIter);
		while (pcTriangle)
		{
			if (pcTriangle->maiVisible.NumElements() > 0)
			{
				if (pcTriangle->NotContains(psPosition))
				{
					cDeleted.Add(&pcTriangle);
				}
			}
			pcTriangle = (CExtremeTriangle*)mcTriangles.Iterate(&sIter);
		}
		
		RemoveDiscontiguousTriangles(pcSelected, &cDeleted, &cFixedDeleted);

		for (j = 0; j < cDeleted.NumElements(); j++)
		{
			pcDeleted = *cDeleted.Get(j);
			FindEdges(&sEdges, pcDeleted, &cDeleted);

			for (k = 0; k < sEdges.iNumEdges; k++)
			{
				pcTriangle = AddTriangle(GetPosition(mpsPoints, iStride, sEdges.aaiEdgeIndices[k][0]),
					GetPosition(mpsPoints, iStride, sEdges.aaiEdgeIndices[k][1]),
					GetPosition(mpsPoints, iStride, iFarIndex));

				apcTriangles.Add(&pcTriangle);
				AddPointsFromTriangles(pcTriangle, &cDeleted, iFarIndex);
			}
		}

		for (j = 0; j < cDeleted.NumElements(); j++)
		{
			pcDeleted = *cDeleted.Get(j);
			pcDeleted->Kill();
			mcTriangles.Remove(pcDeleted);

			iIndex = apcTriangles.FindWithIntKey((int)(size_t)pcDeleted, 0);
			*(apcTriangles.Get(iIndex)) = NULL;
		}
	}
	cDeleted.Kill();
	cFixedDeleted.Kill();

	apcTriangles.Kill();

	RemoveSlivers();

	if (mszHullName)
	{
		CChars szTemp;
		szTemp.Init("Writing Hull file [");
		szTemp.Append(mszHullName);
		szTemp.Append("]\n");
		szTemp.Kill();
		cTextFile.Init();
		DumpTriangleObj(&cTextFile.mcText, iTriangle);
		cTextFile.Write(mszHullName);
		cTextFile.Kill();
	}

	return TRUE;
}