Beispiel #1
0
void DrawPointGPSTool::newGPSPosition(MapCoordF coord, float accuracy)
{
	PointSymbol* point = reinterpret_cast<PointSymbol*>(editor->activeSymbol());
	
	// Calculate weight from accuracy. This is arbitrarily chosen.
	float weight;
	if (accuracy < 0)
		weight = 1; // accuracy unknown
	else
		weight = 1.0f / qMax(0.5f, accuracy);
	
	if (! preview_object)
	{
		// This is the first received position.
		preview_object = new PointObject(point);

		x_sum = weight * coord.x();
		y_sum = weight * coord.y();
		weights_sum = weight;
	}
	else
	{
		renderables->removeRenderablesOfObject(preview_object, false);
		if (preview_object->getSymbol() != point)
		{
			bool success = preview_object->setSymbol(point, true);
			Q_ASSERT(success);
			Q_UNUSED(success);
		}
		
		x_sum += weight * coord.x();
		y_sum += weight * coord.y();
		weights_sum += weight;
	}
	
	MapCoordF avg_position(x_sum / weights_sum, y_sum / weights_sum);
	preview_object->setPosition(avg_position);
	preview_object->setRotation(0);
	preview_object->update();
	renderables->insertRenderablesOfObject(preview_object);
	updateDirtyRect();
}
void LaplaceMeshSmoother::smooth(unsigned int n_iterations)
{
  if (!_initialized)
    this->init();

  // Don't smooth the nodes on the boundary...
  // this would change the mesh geometry which
  // is probably not something we want!
  std::vector<bool> on_boundary;
  MeshTools::find_boundary_nodes(_mesh, on_boundary);

  // Ensure that the find_boundary_nodes() function returned a properly-sized vector
  if (on_boundary.size() != _mesh.max_node_id())
    libmesh_error_msg("MeshTools::find_boundary_nodes() returned incorrect length vector!");

  // We can only update the nodes after all new positions were
  // determined. We store the new positions here
  std::vector<Point> new_positions;

  for (unsigned int n=0; n<n_iterations; n++)
    {
      new_positions.resize(_mesh.max_node_id());

      {
        MeshBase::node_iterator       it     = _mesh.local_nodes_begin();
        const MeshBase::node_iterator it_end = _mesh.local_nodes_end();
        for (; it != it_end; ++it)
          {
            Node * node = *it;

            if (node == libmesh_nullptr)
              libmesh_error_msg("[" << _mesh.processor_id() << "]: Node iterator returned NULL pointer.");

            // leave the boundary intact
            // Only relocate the nodes which are vertices of an element
            // All other entries of _graph (the secondary nodes) are empty
            if (!on_boundary[node->id()] && (_graph[node->id()].size() > 0))
              {
                Point avg_position(0.,0.,0.);

                for (unsigned j=0; j<_graph[node->id()].size(); ++j)
                  {
                    // Will these nodal positions always be available
                    // or will they refer to remote nodes?  This will
                    // fail an assertion in the latter case, which
                    // shouldn't occur if DistributedMesh is working
                    // correctly.
                    const Point & connected_node = _mesh.point(_graph[node->id()][j]);

                    avg_position.add( connected_node );
                  } // end for(j)

                // Compute the average, store in the new_positions vector
                new_positions[node->id()] = avg_position / static_cast<Real>(_graph[node->id()].size());
              } // end if
          } // end for
      } // end scope


      // now update the node positions (local node positions only)
      {
        MeshBase::node_iterator it           = _mesh.local_nodes_begin();
        const MeshBase::node_iterator it_end = _mesh.local_nodes_end();
        for (; it != it_end; ++it)
          {
            Node * node = *it;

            if (!on_boundary[node->id()] && (_graph[node->id()].size() > 0))
              {
                // Should call Point::op=
                // libMesh::out << "Setting node id " << node->id() << " to position " << new_positions[node->id()];
                _mesh.node_ref(node->id()) = new_positions[node->id()];
              }
          } // end for
      } // end scope

      // Now the nodes which are ghosts on this processor may have been moved on
      // the processors which own them.  So we need to synchronize with our neighbors
      // and get the most up-to-date positions for the ghosts.
      SyncNodalPositions sync_object(_mesh);
      Parallel::sync_dofobject_data_by_id
        (_mesh.comm(), _mesh.nodes_begin(), _mesh.nodes_end(), sync_object);

    } // end for n_iterations

  // finally adjust the second order nodes (those located between vertices)
  // these nodes will be located between their adjacent nodes
  // do this element-wise
  MeshBase::element_iterator       el  = _mesh.active_elements_begin();
  const MeshBase::element_iterator end = _mesh.active_elements_end();

  for (; el != end; ++el)
    {
      // Constant handle for the element
      const Elem * elem = *el;

      // get the second order nodes (son)
      // their element indices start at n_vertices and go to n_nodes
      const unsigned int son_begin = elem->n_vertices();
      const unsigned int son_end   = elem->n_nodes();

      // loop over all second order nodes (son)
      for (unsigned int son=son_begin; son<son_end; son++)
        {
          // Don't smooth second-order nodes which are on the boundary
          if (!on_boundary[elem->node_id(son)])
            {
              const unsigned int n_adjacent_vertices =
                elem->n_second_order_adjacent_vertices(son);

              // calculate the new position which is the average of the
              // position of the adjacent vertices
              Point avg_position(0,0,0);
              for (unsigned int v=0; v<n_adjacent_vertices; v++)
                avg_position +=
                  _mesh.point( elem->node_id( elem->second_order_adjacent_vertex(son,v) ) );

              _mesh.node_ref(elem->node_id(son)) = avg_position / n_adjacent_vertices;
            }
        }
    }
}