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; } } } }