Example #1
0
    static inline bool are_holes_inside(RingIterator first,
                                        RingIterator beyond,
                                        ExteriorRing const& exterior_ring,
                                        IndexSet const& rings_with_turns)
    {
        int idx = 0;
        for (RingIterator it = first; it != beyond; ++it, ++idx)
        {
            // check only rings whose index is not associated to any turn
            if ( rings_with_turns.find(idx) == rings_with_turns.end()
                 && !geometry::within(range::front(*it), exterior_ring) )
            {
                return false;
            }
        }

        // for those rings that do not have any associated turns,
        // check if they lie inside another ring
        idx = 0;
        for (RingIterator it1 = first; it1 != beyond; ++it1, ++idx)
        {
            if ( rings_with_turns.find(idx) == rings_with_turns.end() )
            {
                for (RingIterator it2 = first; it2 != beyond; ++it2)
                {
                    if ( it1 != it2
                         && geometry::within(range::front(*it1), *it2) )
                    {
                        return false;
                    }
                }
            }
        }
        return true;
    }
bool isDup(const IndexSet& data, const BSONObj& key, RecordId loc) {
    const IndexSet::const_iterator it = data.find(IndexKeyEntry(key, RecordId()));
    if (it == data.end())
        return false;

    // Not a dup if the entry is for the same loc.
    return it->loc != loc;
}
bool isDup(const IndexSet& data, const BSONObj& key) {
    IndexSet::const_iterator it = data.find(IndexKeyEntry(key, RecordId()));
    if (it == data.end())
        return false;

    ++it;
    if (it == data.end())
        return false;

    return it->key.woCompare(key, BSONObj(), false) == 0;
}
//-----------------------------------------------------------------------------
void RegularCutRefinement::refine_marked(Mesh& refined_mesh,
                                  const Mesh& mesh,
                                  const std::vector<int>& refinement_markers,
                                  const IndexSet& marked_edges)
{
  // Count the number of cells in refined mesh
  std::size_t num_cells = 0;

  // Data structure to hold a cell
  std::vector<std::size_t> cell_data(3);

  for (CellIterator cell(mesh); !cell.end(); ++cell)
  {
    const int marker = refinement_markers[cell->index()];
    switch (marker)
    {
    case no_refinement:
      num_cells += 1;
      break;
    case regular_refinement:
      num_cells += 4;
      break;
    case backtrack_bisection:
      num_cells += 2;
      break;
    case backtrack_bisection_refine:
      num_cells += 3;
      break;
    default:
      num_cells += 2;
    }
  }

  // Initialize mesh editor
  const std::size_t num_vertices = mesh.num_vertices() + marked_edges.size();
  MeshEditor editor;
  editor.open(refined_mesh, mesh.topology().dim(), mesh.geometry().dim());
  editor.init_vertices(num_vertices);
  editor.init_cells(num_cells);

  // Set vertex coordinates
  std::size_t current_vertex = 0;
  for (VertexIterator vertex(mesh); !vertex.end(); ++vertex)
  {
    editor.add_vertex(current_vertex, vertex->point());
    current_vertex++;
  }
  for (std::size_t i = 0; i < marked_edges.size(); i++)
  {
    Edge edge(mesh, marked_edges[i]);
    editor.add_vertex(current_vertex, edge.midpoint());
    current_vertex++;
  }

  // Get bisection data for old mesh
  const std::size_t D = mesh.topology().dim();
  const std::vector<std::size_t>*  bisection_twins = NULL;
  if (mesh.data().exists("bisection_twins", D))
    bisection_twins = &(mesh.data().array("bisection_twins", D));

  // Markers for bisected cells pointing to their bisection twins in
  // refined mesh
  std::vector<std::size_t>& refined_bisection_twins
    = refined_mesh.data().create_array("bisection_twins", D);
  refined_bisection_twins.resize(num_cells);
  for (std::size_t i = 0; i < num_cells; i++)
    refined_bisection_twins[i] = i;

  // Mapping from old to new unrefined cells (-1 means refined or not
  // yet processed)
  std::vector<int> unrefined_cells(mesh.num_cells());
  std::fill(unrefined_cells.begin(), unrefined_cells.end(), -1);

  // Iterate over all cells and add new cells
  std::size_t current_cell = 0;
  std::vector<std::vector<std::size_t> > cells(4, std::vector<std::size_t>(3));
  for (CellIterator cell(mesh); !cell.end(); ++cell)
  {
    // Get marker
    const int marker = refinement_markers[cell->index()];

    if (marker == no_refinement)
    {
      // No refinement: just copy cell to new mesh

      std::vector<std::size_t> vertices;
      for (VertexIterator vertex(*cell); !vertex.end(); ++vertex)
        vertices.push_back(vertex->index());
      editor.add_cell(current_cell++, vertices);

      // Store mapping to new cell index
      unrefined_cells[cell->index()] = current_cell - 1;

      // Remember unrefined bisection twins
      if (bisection_twins)
      {
        const std::size_t bisection_twin = (*bisection_twins)[cell->index()];
        const int twin_marker = refinement_markers[bisection_twin];
        dolfin_assert(twin_marker == no_refinement);
        if (unrefined_cells[bisection_twin] >= 0)
        {
          const std::size_t i = current_cell - 1;
          const std::size_t j = unrefined_cells[bisection_twin];
          refined_bisection_twins[i] = j;
          refined_bisection_twins[j] = i;
        }
      }
    }
    else if (marker == regular_refinement)
    {
      // Regular refinement: divide into subsimplicies
      dolfin_assert(unrefined_cells[cell->index()] == -1);

      // Get vertices and edges
      const unsigned int* v = cell->entities(0);
      const unsigned int* e = cell->entities(1);
      dolfin_assert(v);
      dolfin_assert(e);

      // Get offset for new vertex indices
      const std::size_t offset = mesh.num_vertices();

      // Compute indices for the six new vertices
      const std::size_t v0 = v[0];
      const std::size_t v1 = v[1];
      const std::size_t v2 = v[2];
      const std::size_t e0 = offset + marked_edges.find(e[0]);
      const std::size_t e1 = offset + marked_edges.find(e[1]);
      const std::size_t e2 = offset + marked_edges.find(e[2]);

      // Create four new cells
      cells[0][0] = v0; cells[0][1] = e2; cells[0][2] = e1;
      cells[1][0] = v1; cells[1][1] = e0; cells[1][2] = e2;
      cells[2][0] = v2; cells[2][1] = e1; cells[2][2] = e0;
      cells[3][0] = e0; cells[3][1] = e1; cells[3][2] = e2;

      // Add cells
      std::vector<std::vector<std::size_t> >::const_iterator _cell;
      for (_cell = cells.begin(); _cell != cells.end(); ++_cell)
        editor.add_cell(current_cell++, *_cell);
    }
    else if (marker == backtrack_bisection || marker == backtrack_bisection_refine)
    {
      // Special case: backtrack bisected cells
      dolfin_assert(unrefined_cells[cell->index()] == -1);

      // Get index for bisection twin
      dolfin_assert(bisection_twins);
      const std::size_t bisection_twin = (*bisection_twins)[cell->index()];
      dolfin_assert(bisection_twin != cell->index());

      // Let lowest number twin handle refinement
      if (bisection_twin < cell->index())
        continue;

      // Get marker for twin
      const int twin_marker = refinement_markers[bisection_twin];

      // Find common edge(s) and bisected edge(s)
      const std::pair<std::size_t, std::size_t> common_edges
        = find_common_edges(*cell, mesh, bisection_twin);
      const std::pair<std::size_t, std::size_t> bisection_edges
        = find_bisection_edges(*cell, mesh, bisection_twin);
      const std::pair<std::size_t, std::size_t> bisection_vertices
        = find_bisection_vertices(*cell, mesh, bisection_twin, bisection_edges);

      // Get list of vertices and edges for both cells
      const Cell twin(mesh, bisection_twin);
      const unsigned int* vertices_0 = cell->entities(0);
      const unsigned int* vertices_1 = twin.entities(0);
      const unsigned int* edges_0 = cell->entities(1);
      const unsigned int* edges_1 = twin.entities(1);
      dolfin_assert(vertices_0);
      dolfin_assert(vertices_1);
      dolfin_assert(edges_0);
      dolfin_assert(edges_1);

      // Get offset for new vertex indices
      const std::size_t offset = mesh.num_vertices();

      // Locate vertices such that v_i is the vertex opposite to
      // the edge e_i on the parent triangle
      const std::size_t v0 = vertices_0[common_edges.first];
      const std::size_t v1 = vertices_1[common_edges.second];
      const std::size_t v2 = vertices_0[bisection_edges.first];
      const std::size_t e0 = offset + marked_edges.find(edges_1[bisection_vertices.second]);
      const std::size_t e1 = offset + marked_edges.find(edges_0[bisection_vertices.first]);
      const std::size_t e2 = vertices_0[bisection_vertices.first];

      // Locate new vertices on bisected edge (if any)
      std::size_t E0 = 0;
      std::size_t E1 = 0;
      if (marker == backtrack_bisection_refine)
        E0 = offset + marked_edges.find(edges_0[bisection_edges.first]);
      if (twin_marker == backtrack_bisection_refine)
        E1 = offset + marked_edges.find(edges_1[bisection_edges.second]);

      // Add middle two cells (always)
      dolfin_assert(cell_data.size() == 3);
      cell_data[0] = e0; cell_data[1] = e1; cell_data[2] = e2;
      editor.add_cell(current_cell++, cell_data);

      cell_data[0] = v2; cell_data[1] = e1; cell_data[2] = e0;
      editor.add_cell(current_cell++, cell_data);

      // Add one or two remaining cells in current cell (left)
      if (marker == backtrack_bisection)
      {
        cell_data[0] = v0; cell_data[1] = e2; cell_data[2] = e1;
        editor.add_cell(current_cell++, cell_data);
      }
      else
      {
        // Add the two cells
        cell_data[0] = v0; cell_data[1] = E0; cell_data[2] = e1;
        editor.add_cell(current_cell++, cell_data);

        cell_data[0] = E0; cell_data[1] = e2; cell_data[2] = e1;
        editor.add_cell(current_cell++, cell_data);

        // Set bisection twins
        refined_bisection_twins[current_cell - 2] = current_cell - 1;
        refined_bisection_twins[current_cell - 1] = current_cell - 2;
      }

      // Add one or two remaining cells in twin cell (right)
      if (twin_marker == backtrack_bisection)
      {
        cell_data[0] = v1; cell_data[1] = e0; cell_data[2] = e2;
        editor.add_cell(current_cell++, cell_data);
      }
      else
      {
        // Add the two cells
        cell_data[0] = v1; cell_data[1] = e0; cell_data[2] = E1;
        editor.add_cell(current_cell++, cell_data);

        cell_data[0] = e0; cell_data[1] = e2; cell_data[2] = E1;
        editor.add_cell(current_cell++, cell_data);

        // Set bisection twins
        refined_bisection_twins[current_cell - 2] = current_cell - 1;
        refined_bisection_twins[current_cell - 1] = current_cell - 2;
      }
    }
    else
    {
      // One edge marked for refinement: do bisection

      dolfin_assert(unrefined_cells[cell->index()] == -1);

      // Get vertices and edges
      const unsigned int* v = cell->entities(0);
      const unsigned int* e = cell->entities(1);
      dolfin_assert(v);
      dolfin_assert(e);

      // Get edge number (equal to marker)
      dolfin_assert(marker >= 0);
      const std::size_t local_edge_index = static_cast<std::size_t>(marker);
      const std::size_t global_edge_index = e[local_edge_index];
      const std::size_t ee = mesh.num_vertices() + marked_edges.find(global_edge_index);

      // Add the two new cells
      if (local_edge_index == 0)
      {
        cell_data[0] = v[0]; cell_data[1] = ee; cell_data[2] = v[1];
        editor.add_cell(current_cell++, cell_data);

        cell_data[0] = v[0]; cell_data[1] = ee; cell_data[2] = v[2];
        editor.add_cell(current_cell++, cell_data);
      }
      else if (local_edge_index == 1)
      {
        cell_data[0] = v[1]; cell_data[1] = ee; cell_data[2] = v[0];
        editor.add_cell(current_cell++, cell_data);

        cell_data[0] = v[1]; cell_data[1] = ee; cell_data[2] = v[2];
        editor.add_cell(current_cell++, cell_data);
      }
      else
      {
        cell_data[0] = v[2]; cell_data[1] = ee; cell_data[2] = v[0];
        editor.add_cell(current_cell++, cell_data);

        cell_data[0] = v[2]; cell_data[1] = ee; cell_data[2] = v[1];
        editor.add_cell(current_cell++, cell_data);
      }

      // Set bisection twins
      refined_bisection_twins[current_cell - 2] = current_cell - 1;
      refined_bisection_twins[current_cell - 1] = current_cell - 2;
    }
  }

  // Close mesh editor
  dolfin_assert(num_cells == current_cell);
  editor.close();
}
bool keyExists(const IndexSet& data, const BSONObj& key) {
    IndexSet::const_iterator it = data.find(IndexKeyEntry(key, RecordId()));
    return it != data.end();
}
Example #6
0
void
TopologyGraph::createBoundary(unsigned graphNum, TopologyGraph::IndexVector& output) const
{
    // nothing to do - bail
    if (_verts.empty() || graphNum+1 > _maxGraphID)
        return;

    // graph ID is one more than the graph number passed in:
    unsigned graphID = graphNum + 1u;

    // Find the starting point (vertex with minimum Y) for this graph ID.
    // By the nature of disconnected graphs, that start point is all we need
    // to ensure we are walking a single connected mesh.
    Index vstart = _verts.end();
    for (VertexSet::const_iterator vert = _verts.begin(); vert != _verts.end(); ++vert)
    {
        if (vert->_graphID == graphID) 
        {
            if (vstart == _verts.end() || vert->y() < vstart->y())
            {
                vstart = vert;
            }
        }
    }

    // couldn't find a start point - bail (should never happen)
    if (vstart == _verts.end())
        return;

    // starting with the minimum-Y vertex (which is guaranteed to be in the boundary)
    // traverse the outside of the point set. Do this by sorting all the edges by
    // their angle relative to the vector from the previous point. The "leftest" turn
    // represents the edge connecting the current point to the next boundary point.
    // Thusly we walk the boundary counterclockwise until we return to the start point.
    Index vptr = vstart;
    Index vptr_prev = _verts.end();

    IndexSet visited;

    while( true )
    {
        // store this vertex in the result set:
        output.push_back( vptr );

        // pull up the next 2D vertex (XY plane):
        osg::Vec2d vert ( vptr->x(), vptr->y() );

        // construct the "base" vector that points from the previous 
        // point to the current point; or to +X in the initial case
        osg::Vec2d base;
        if ( vptr_prev == _verts.end() )
        {
            base.set(1, 0);
        }
        else
        {
            base = vert - osg::Vec2d( vptr_prev->x(), vptr_prev->y() );
            base.normalize();
        }
            
        // pull up the edge set for this vertex:
        EdgeMap::const_iterator ei = _edgeMap.find(vptr);
        if (ei == _edgeMap.end())
            continue; // should be impossible

        const IndexSet& edges = ei->second;

        // find the edge with the minimum delta angle to the base vector
        double bestScore = -DBL_MAX;
        Index  bestEdge  = _verts.end();
        
        //OE_NOTICE << "VERTEX (" << 
        //    vptr->x() << ", " << vptr->y() << ", "
        //    << ") has " << edges.size() << " edges..."
        //    << std::endl;

        unsigned possibleEdges = 0u;

        for( IndexSet::iterator e = edges.begin(); e != edges.end(); ++e )
        {
            // don't go back from whence we just came
            if ( *e == vptr_prev )
                continue;

            // never return to a vert we've already visited
            if ( visited.find(*e) != visited.end() )
                continue;

            ++possibleEdges;

            // calculate the angle between the base vector and the current edge:
            osg::Vec2d edgeVert( (*e)->x(), (*e)->y() );
            osg::Vec2d edge = edgeVert - vert;
            edge.normalize();

            double cross = base.x()*edge.y() - base.y()*edge.x();
            double dot   = base * edge;

            double score;
            if (cross <= 0.0)
                score = 1.0-dot; // [0..2]
            else
                score = dot-1.0; // [-2..0]

            //OE_NOTICE << "   check: " << (*e)->x() << ", " << (*e)->y() << std::endl;
            //OE_NOTICE << "   base = " << base.x() << ", " << base.y() << std::endl;
            //OE_NOTICE << "   edge = " << edge.x() << ", " << edge.y() << std::endl;
            //OE_NOTICE << "   crs = " << cross << ", dot = " << dot << ", score = " << score << std::endl;
            
            if (score > bestScore)
            {
                bestScore = score;
                bestEdge = *e;
            }
        }

        if ( bestEdge == _verts.end() )
        {
            // this should never happen
            // but sometimes does anyway
            OE_WARN << LC << getName() << " - Illegal state - reached a dead end during boundary detection. Vertex (" 
                << vptr->x() << ", " << vptr->y() << ") has " << possibleEdges << " possible edges.\n"
                << std::endl;
            break;
        }

        // store the previous:
        vptr_prev = vptr;

        // follow the chosen edge around the outside of the geometry:
        //OE_DEBUG << "   BEST SCORE = " << bestScore << std::endl;
        vptr = bestEdge;

        // record this vert so we don't visit it again.
        visited.insert( vptr );

        // once we make it all the way around, we're done:
        if ( vptr == vstart )
            break;
    }
}