Example #1
0
void AdvancingFront::compute_advancing(dolfin::Mesh * blue_mesh, dolfin::Mesh * red_mesh, size_t seed_red, size_t seed_blue)
{
    double P[24];
    int nP = 0; // intersection points
    int nc[3] = { -1, -1, -1 }; // means no intersection on the side (markers)
    int found = 0;
    // Checking if seed is intersecting.
    computeIntersectionBetweenRedAndBlue(red_mesh, blue_mesh, seed_red, seed_blue, P, nP, nc);
    if (nP > 0)
    {
        found = 1;
    }

    size_t start_blue = seed_blue;
    size_t start_red = seed_red;

    // If seed is not intersecting, brute force first intersection.
    if(!found)
    {

        for (dolfin::CellIterator r(*red_mesh); !r.end(); ++r)
        {
            start_red = r->global_index();

        for (dolfin::CellIterator b(*blue_mesh); !b.end(); ++b)
        {
                start_blue = b->global_index();

                double P[24];
                int nP = 0; // intersection points
                int nc[3] = { -1, -1, -1 }; // means no intersection on the side (markers)
                computeIntersectionBetweenRedAndBlue(red_mesh, blue_mesh, start_red, start_blue, P, nP, nc);
                if (nP > 0) {
                    found = 1;
                    break;
                }
        }
        if(found) break;
        }
    }

    if(!found) {
    std::cout << "could not find seed" << std::endl;
    return;
    }

    std::queue<int> blueQueue;
    blueQueue.push(start_blue);

    std::queue<int> redQueue;
    /// Vector performs better than set. We do not know
    /// how many neighbours get marked, so some kind of
    /// dynamic container is necassary.
    std::vector<int> redschanged;
    redQueue.push(start_red);

    // the flags are used for marking the triangles already considered
    int m_numNeg = blue_mesh->num_cells();
    int m_numPos = red_mesh->num_cells();
    int * blueFlag = new int [m_numNeg + 1]; // number of blue triangles + 1, to account for the boundary
    int k=0;
    for (k=0; k<m_numNeg + 1; k++)
        blueFlag[k] = -1;
    blueFlag[m_numNeg] = 1; // mark the "boundary"; stop at the boundary
    blueFlag[start_blue] = 1; // mark also the first one
    // also, red flag is declared outside the loop
    int * redFlag = new int [m_numPos +1];
    redFlag[0] = -1;
    memset(&redFlag[0], -1, (m_numPos +1) * sizeof redFlag[0]);
    while( !blueQueue.empty() )
    {
        int n[3]; // flags for the side : indices in red mesh start from 0!!! (-1 means not found )
        for (k=0; k<3; k++)
            n[k] = -1; // a paired red not found yet for the neighbors of blue

        int currentBlue = blueQueue.front();
        blueQueue.pop();

        /// This is what in the MOAB implementation made it
        /// exponential. Is there some compiler flag that can make this linear?
        /*
        for (k=0; k<m_numPos +1; k++)
            redFlag[k] = -1;
        */
        /// Memset makes it less exponential (without compiler flag -O3).
        /*
        memset(&redFlag[0], -1, (m_numPos +1) * sizeof redFlag[0]);
        */
        /// Using a set makes it linear (optimal?).
        for (std::vector<int>::iterator it=redschanged.begin(); it!=redschanged.end(); ++it) {
            redFlag[*it] = -1;
        }

        redschanged.clear();
        redFlag[0] = -1;
        redschanged.push_back(0);
        redFlag[m_numPos + 1] = -1; // to guard for the boundary
        redschanged.push_back(m_numPos + 1);
        int currentRed = redQueue.front(); // where do we check for redQueue????

        // red and blue queues are parallel
        redQueue.pop();//
        redFlag[currentRed] = 1; //
        redschanged.push_back(currentRed);
        std::queue<int> localRed;
        localRed.push(currentRed);
        while( !localRed.empty())
        {
            //
            int redT = localRed.front();
            localRed.pop();
            double P[24], area;
            int nP = 0; // intersection points
            int nc[3]= {-1, -1, -1}; // means no intersection on the side (markers)

            computeIntersectionBetweenRedAndBlue(red_mesh, blue_mesh, redT, currentBlue, P, nP, nc);

            if (nP > 0)
            {
                intersectionsetFirstMesh[currentBlue].push_back(redT);
                // add neighbors to the localRed queue, if they are not marked
                int neighbors[3];
                // rval = get_ordererd_neighbours(mb2, mbs2, redT, neighbors);
                get_ordered_neighbours(red_mesh, redT, neighbors);
                // add neighbors to the localRed queue, if they are not marked
                for (int nn= 0; nn<3; nn++)
                {
                    int neighbor = neighbors[nn];
                    if (neighbor > -1) {
                        if (redFlag[neighbor] == -1)
                        {
                            localRed.push(neighbor);
                            redFlag[neighbor] = 1; // flag it to not be added anymore
                            redschanged.push_back(neighbor);
                        }
                        // n(find(nc>0))=ac;        % ac is starting candidate for neighbor
                        if (nc[nn] > -1) // intersected
                            n[nn] = redT;// start from 0!!
                    }
                }
            }
        }
        int blueNeighbors[3];
        get_ordered_neighbours(blue_mesh, currentBlue, blueNeighbors);
        for (int j=0; j<3; j++)
        {
            int blueNeigh = blueNeighbors[(j+2)%3];

            if (blueFlag[blueNeigh] == -1 && n[j] > -1 ) // not treated yet and marked as a neighbor
            {
                // we identified triangle n[j] as intersecting with neighbor j of the blue triangle
                blueQueue.push(blueNeigh);
                redQueue.push(n[j]);
                blueFlag[blueNeigh] = 1;
            }

        }
    }
    delete [] redFlag;
    redFlag = NULL;

    delete [] blueFlag; // get rid of it
    blueFlag = NULL;
    //    return 0;
}
Example #2
0
int ProjectShell::computeIntersections()
{
  // will start at 2 triangles, and advance an intersection front (2 queues, one for red triangles, one for blue ..)
  // will mark a red triangle that is processed, and add to the queue
  // for each red triangle will find all the blue triangles that are intersected
  // find first 2 triangles that intersect: these will be the seeds for intersection

  int startRed=0;
  int startBlue = 0;
  for (startBlue = 0; startBlue<m_numNeg; startBlue++)
    {
      double area = 0;
      // if area is > 0 , we have intersections
      double P[24]; // max 6 points, but it may grow bigger; why worry
      int nP = 0;
      int n[3];// sides
      computeIntersectionBetweenRedAndBlue(/* red */0, startBlue, P, nP, area,n);
      if (area>0)
	break; // found 2 triangles that intersect; these will be the seeds
    }
  if (startBlue==m_numNeg)
    {
      // can't find any triangle stop
      exit (1);
    }
  // on the red edges, we will keep a list of new points (in 2D)
  // they will be used to create or not new points for points P from intersection
  // (sometimes the points P are either on sides, or on vertices of blue or even red triangles)

  /*
    matlab code: 
    function M=InterfaceMatrix(Na,Ta,Nb,Tb);
    % INTERFACEMATRIX projection matrix for nonmatching triangular grids 
    %   M=InterfaceMatrix(Na,Ta,Nb,Tb); takes two triangular meshes Ta
    %   and Tb with associated nodal coordinates in Na and Nb and
    %   computes the interface projection matrix M

    bl=[1];                        % bl: list of triangles of Tb to treat
    bil=[1];                       % bil: list of triangles Ta to start with
    bd=zeros(size(Tb,1)+1,1);      % bd: flag for triangles in Tb treated 
    bd(end)=1;                     % guard, to treat boundaries
    bd(1)=1;                       % mark first triangle in b list.
    M=sparse(size(Nb,2),size(Na,2));
    while length(bl)>0
    bc=bl(1); bl=bl(2:end);      % bc: current triangle of Tb 
    al=bil(1); bil=bil(2:end);   % triangle of Ta to start with
    ad=zeros(size(Ta,1)+1,1);    % same as for bd
    ad(end)=1;
    ad(al)=1; 
    n=[0 0 0];                   % triangles intersecting with neighbors
    while length(al)>0
    ac=al(1); al=al(2:end);    % take next candidate
    [P,nc,Mc]=Intersect(Nb(:,Tb(bc,1:3)),Na(:,Ta(ac,1:3)));
    if ~isempty(P)             % intersection found
    M(Tb(bc,1:3),Ta(ac,1:3))=M(Tb(bc,1:3),Ta(ac,1:3))+Mc;
    t=Ta(ac,3+find(ad(Ta(ac,4:6))==0)); 
    al=[al t];               % add neighbors 
    ad(t)=1;
    n(find(nc>0))=ac;        % ac is starting candidate for neighbor  
    end
    end
    tmp=find(bd(Tb(bc,4:6))==0); % find non-treated neighbors
    idx=find(n(tmp)>0);          % take those which intersect
    t=Tb(bc,3+tmp(idx));
    bl=[bl t];                   % and add them
    bil=[bil n(tmp(idx))];       % with starting candidates Ta
    bd(t)=1;
    end
  */
  std::queue<int> blueQueue; // these are corresponding to Ta,
  blueQueue.push( startBlue);
  std::queue<int> redQueue;
  redQueue.push (startRed);
  // the flags are used for marking the triangles already considered
  int * blueFlag = new int [m_numNeg+1]; // number of blue triangles + 1, to account for the boundary
  int k=0;
  for (k=0; k<m_numNeg; k++)
    blueFlag[k] = 0;
  blueFlag[m_numNeg] = 1; // mark the "boundary"; stop at the boundary
  blueFlag[startBlue] = 1; // mark also the first one
  // also, red flag is declared outside the loop
  int * redFlag = new int [m_numPos+1];
  
  if (dbg)
    mout.open("patches.m");
  while( !blueQueue.empty() )
    {
      int n[3]; // flags for the side : indices in red mesh start from 0!!! (-1 means not found )
      for (k=0; k<3; k++)
	n[k] = -1; // a paired red not found yet for the neighbors of blue 
      int currentBlue = blueQueue.front();
      blueQueue.pop();
      for (k=0; k<m_numPos; k++)
	redFlag[k] = 0;
      redFlag[m_numPos] = 1; // to guard for the boundary
      int currentRed = redQueue.front(); // where do we check for redQueue???? 
      // red and blue queues are parallel
      redQueue.pop();// 
      redFlag[currentRed] = 1; // 
      std::queue<int> localRed;
      localRed.push(currentRed);
      while( !localRed.empty())
	{
	  // 
	  int redT = localRed.front();
	  localRed.pop();
	  double P[24], area;
          int nP = 0; // intersection points
	  int nc[3]= {0, 0, 0}; // means no intersection on the side (markers)
          computeIntersectionBetweenRedAndBlue(/* red */redT, currentBlue, P, nP, area,nc);
	  if (nP>0) 
	    {
	      // intersection found: output P and original triangles if nP > 2
	      if (dbg && area>0)
		{
		  //std::cout << "area: " << area<< " nP:"<<nP << " sources:" << redT+1 << ":" << m_redMesh[redT].oldId <<
		  //  " " << currentBlue+1<< ":" << m_blueMesh[currentBlue].oldId << std::endl;
		}
              if (dbg)
		{
		  mout << "pa=[\n";
		  
		  for (k=0; k<nP; k++)
		    {
		     
		      mout <<  P[2*k] << "\t " ;
		    }
	
		  mout << "\n";
		  for (k=0; k<nP; k++)
		    {
		    
		      mout << P[2*k+1] << "\t "; 
		    }
	
		  mout << " ]; \n";
		  mout << " patch(pa(1,:),pa(2,:),'m');       \n";
		}
	      // add neighbors to the localRed queue, if they are not marked
	      for (int nn= 0; nn<3; nn++)
		{
		  int neighbor = m_redMesh[redT].t[nn];
		  if (redFlag[neighbor] == 0)
		    {
		      localRed.push(neighbor);
		      redFlag[neighbor] =1; // flag it to not be added anymore
		    }
		  // n(find(nc>0))=ac;        % ac is starting candidate for neighbor
		  if (nc[nn]>0) // intersected  
		    n[nn] = redT;// start from 0!! 
		}
              if (nP>1) // this will also construct triangles, if needed
		findNodes(redT, currentBlue, P, nP);
	    }
	  
	}
      for (int j=0; j<3; j++)
	{
	  int blueNeigh = m_blueMesh[currentBlue].t[j];
	  if (blueFlag[blueNeigh]==0 && n[j] >=0 ) // not treated yet and marked as a neighbor
	    {
              // we identified triangle n[j] as intersecting with neighbor j of the blue triangle
	      blueQueue.push(blueNeigh);
	      redQueue.push(n[j]);
	      if (dbg)
		std::cout << "new triangles pushed: blue, red:" << blueNeigh+1 << " " << n[j]+1 << std::endl;
	      blueFlag[blueNeigh] = 1;
	    }
	}
    }
  delete [] redFlag;
  redFlag = NULL;

  delete [] blueFlag; // get rid of it
  blueFlag = NULL;
  if (dbg)
    mout.close();
  return 0;
}