Example #1
0
TEST_F(GeoLibOctTree, TestWithAlternatingPoints3d)
{
    // this case is not correctly handled by lexicographical sorting
    double const eps(1e-1);
    double const small_displacement(1e-2);
    ps_ptr.push_back(new GeoLib::Point(0,0,0,0));
    ps_ptr.push_back(new GeoLib::Point(2*small_displacement,0,0,1));
    ps_ptr.push_back(new GeoLib::Point(small_displacement,1,0,2));
    ps_ptr.push_back(new GeoLib::Point(4*small_displacement,0,0,3));
    ps_ptr.push_back(new GeoLib::Point(3*small_displacement,1,0,4));
    ps_ptr.push_back(new GeoLib::Point(6*small_displacement,0,0,5));
    ps_ptr.push_back(new GeoLib::Point(5*small_displacement,1,0,6));

    GeoLib::AABB const aabb(ps_ptr.cbegin(), ps_ptr.cend());
    const MathLib::Point3d& min(aabb.getMinPoint());
    const MathLib::Point3d& max(aabb.getMaxPoint());
    std::unique_ptr<GeoLib::OctTree<GeoLib::Point, 8>> oct_tree(
        GeoLib::OctTree<GeoLib::Point, 8>::createOctTree(min, max, eps));

    // pt_ptr[0] should be inserted correctly
    GeoLib::Point * ret_pnt(nullptr);
    ASSERT_TRUE(oct_tree->addPoint(ps_ptr[0], ret_pnt));
    ASSERT_EQ(ps_ptr[0], ret_pnt);
    // ps_ptr[1] is in the eps-environment of ps_ptr[0]
    ret_pnt = nullptr;
    ASSERT_FALSE(oct_tree->addPoint(ps_ptr[1], ret_pnt));
    ASSERT_EQ(ps_ptr[0], ret_pnt);
    // pt_ptr[2] should be inserted correctly
    ret_pnt = nullptr;
    ASSERT_TRUE(oct_tree->addPoint(ps_ptr[2], ret_pnt));
    ASSERT_EQ(ps_ptr[2], ret_pnt);
    // ps_ptr[3] is in the eps-environment of ps_ptr[0]
    ret_pnt = nullptr;
    ASSERT_FALSE(oct_tree->addPoint(ps_ptr[3], ret_pnt));
    ASSERT_EQ(ps_ptr[0], ret_pnt);
    // ps_ptr[4] is in the eps-environment of ps_ptr[2]
    ret_pnt = nullptr;
    ASSERT_FALSE(oct_tree->addPoint(ps_ptr[4], ret_pnt));
    ASSERT_EQ(ps_ptr[2], ret_pnt);
    // ps_ptr[5] is in the eps-environment of ps_ptr[0]
    ret_pnt = nullptr;
    ASSERT_FALSE(oct_tree->addPoint(ps_ptr[5], ret_pnt));
    ASSERT_EQ(ps_ptr[0], ret_pnt);
    // ps_ptr[6] is in the eps-environment of ps_ptr[2]
    ret_pnt = nullptr;
    ASSERT_FALSE(oct_tree->addPoint(ps_ptr[6], ret_pnt));
    ASSERT_EQ(ps_ptr[2], ret_pnt);
}
Example #2
0
TEST_F(GeoLibOctTree, TestSmallDistanceDifferentLeaves)
{
    // case where two points with a small distance but different OctTree leaves
    // are inserted
    double const eps(0.5);
    for (std::size_t k = 0; k < 21; ++k) {
        for (std::size_t j = 0; j < 21; ++j) {
            std::size_t id = k*21+j;
            for (std::size_t i = 0; i < 21; ++i) {
                ps_ptr.push_back(new GeoLib::Point(i-10., j-10., k-10., id+i));
            }
        }
    }

    // create OctTree
    GeoLib::AABB const aabb(ps_ptr.cbegin(), ps_ptr.cend());
    const MathLib::Point3d& min(aabb.getMinPoint());
    const MathLib::Point3d& max(aabb.getMaxPoint());
    std::unique_ptr<GeoLib::OctTree<GeoLib::Point, 2>> oct_tree(
        GeoLib::OctTree<GeoLib::Point, 2>::createOctTree(min, max, eps));

    // fill OctTree
    for (auto p : ps_ptr) {
        GeoLib::Point * ret_pnt(nullptr);
        ASSERT_TRUE(oct_tree->addPoint(p, ret_pnt));
        ASSERT_EQ(p, ret_pnt);
    }

    // point near the GeoLib::Point (0, -10, -10, 10) (with id 10)
    std::unique_ptr<GeoLib::Point> p0(new GeoLib::Point(0.1, -10.0, -10.0));
    GeoLib::Point * ret_pnt(nullptr);
    ASSERT_FALSE(oct_tree->addPoint(p0.get(), ret_pnt));
    ASSERT_EQ(10u, ret_pnt->getID());

    (*p0)[0] = -0.1;
    ret_pnt = nullptr;
    ASSERT_FALSE(oct_tree->addPoint(p0.get(), ret_pnt));
    ASSERT_EQ(10u, ret_pnt->getID());
}
void Mesh2MeshPropertyInterpolation::interpolatePropertiesForMesh(Mesh *dest_mesh, std::vector<double>& dest_properties) const
{
    // carry over property information from source elements to source nodes
    std::vector<double> interpolated_src_node_properties(_src_mesh->getNumberOfNodes());
    interpolateElementPropertiesToNodeProperties(interpolated_src_node_properties);

    // looping over the destination elements and calculate properties
    // from interpolated_src_node_properties
    std::vector<MeshLib::Node*> const& src_nodes(_src_mesh->getNodes());

    GeoLib::Grid<MeshLib::Node> src_grid(src_nodes.begin(), src_nodes.end(), 64);

    auto materialIds = dest_mesh->getProperties().getPropertyVector<int>("MaterialIDs");
    if (!materialIds)
        materialIds = dest_mesh->getProperties().createNewPropertyVector<int>(
            "MaterialIDs", MeshLib::MeshItemType::Cell, 1);
    if (!materialIds)
    {
        ERR("Could not create PropertyVector for MaterialIDs in Mesh.");
        return;
    }

    std::vector<MeshLib::Element*> const& dest_elements(dest_mesh->getElements());
    const std::size_t n_dest_elements(dest_elements.size());
    for (std::size_t k(0); k<n_dest_elements; k++)
    {
        // compute axis aligned bounding box around the current element
        const GeoLib::AABB elem_aabb(dest_elements[k]->getNodes(), dest_elements[k]->getNodes()+dest_elements[k]->getNumberOfBaseNodes());

        // request "interesting" nodes from grid
        std::vector<std::vector<MeshLib::Node*> const*> nodes;
        src_grid.getPntVecsOfGridCellsIntersectingCuboid(elem_aabb.getMinPoint(), elem_aabb.getMaxPoint(), nodes);

        std::size_t cnt(0);
        dest_properties[k] = 0.0;

        for (std::size_t i(0); i<nodes.size(); ++i) {
            std::vector<MeshLib::Node*> const* i_th_vec(nodes[i]);
            const std::size_t n_nodes_in_vec(i_th_vec->size());
            for (std::size_t j(0); j<n_nodes_in_vec; j++) {
                MeshLib::Node const*const j_th_node((*i_th_vec)[j]);
                if (elem_aabb.containsPoint(*j_th_node)) {
                    if (dest_elements[k]->isPntInElement(*j_th_node, 30)) {
                        dest_properties[k] += interpolated_src_node_properties[(*i_th_vec)[j]->getID()];
                        cnt++;
                    }
                }
            }
        }

        dest_properties[k] /= cnt;
        materialIds->push_back(k);

        if (cnt == 0) {
            std::string base_name("DebugData/Element-");
            base_name += std::to_string(k);

            std::string aabb_fname(base_name + "-aabb.gli");
            std::ofstream out_aabb(aabb_fname.c_str());
            out_aabb << "#POINTS" << "\n";
            out_aabb << "0 " << elem_aabb.getMinPoint() << "\n";
            out_aabb << "1 " << elem_aabb.getMaxPoint() << "\n";
            out_aabb << "#STOP" << "\n";
            out_aabb.close();


            std::string source_fname(base_name + "-SourceNodes.gli");
            std::ofstream out_src(source_fname.c_str());
            out_src << "#POINTS" << "\n";
            std::size_t nodes_cnt(0);
            for (std::size_t i(0); i<nodes.size(); ++i) {
                std::vector<MeshLib::Node*> const* i_th_vec(nodes[i]);
                const std::size_t n_nodes_in_vec(i_th_vec->size());
                for (std::size_t j(0); j<n_nodes_in_vec; j++) {
                    MeshLib::Node const*const j_th_node((*i_th_vec)[j]);
                    out_src << nodes_cnt << " " << *(dynamic_cast<GeoLib::Point const*>(j_th_node)) << "\n";
                    nodes_cnt++;
                }
            }
            out_src << "#STOP" << "\n";
            out_src.close();
            ERR("no source nodes in dest element %d", k);
        }
    }
}
void MeshElementRemovalDialog::accept()
{
    if (this->newMeshNameEdit->text().size()==0)
    {
        OGSError::box("Please enter name for new mesh.");
        return;
    }

    bool anything_checked (false);

    const MeshLib::Mesh* msh = _project.getMesh(this->meshNameComboBox->currentText().toStdString());
    MeshLib::ElementSearch ex(*msh);
    if (this->elementTypeCheckBox->isChecked())
    {
        QList<QListWidgetItem*> items = this->elementTypeListWidget->selectedItems();
        for (auto& item : items)
            ex.searchByElementType(
                MeshLib::String2MeshElemType(item->text().toStdString()));
        anything_checked = true;
    }
    if (this->scalarArrayCheckBox->isChecked())
    {
        std::string const array_name = this->scalarArrayComboBox->currentText().toStdString();
        double min_val, max_val;
        bool outside = this->outsideButton->isChecked();
        if (outside)
        {
            min_val = this->outsideScalarMinEdit->text().toDouble();
            max_val = this->outsideScalarMaxEdit->text().toDouble();
        }
        else
        {
            min_val = this->insideScalarMinEdit->text().toDouble();
            max_val = this->insideScalarMaxEdit->text().toDouble();
        }
        std::size_t n_marked_elements =
            ex.searchByPropertyValueRange<double>(array_name, min_val, max_val, outside);

        if (n_marked_elements == 0)
            n_marked_elements =
                ex.searchByPropertyValueRange<int>(array_name, min_val, max_val, outside);

        if (n_marked_elements > 0)
            anything_checked = true;
    }
    if (this->boundingBoxCheckBox->isChecked())
    {
        std::vector<MeshLib::Node*> const& nodes (_project.getMesh(this->meshNameComboBox->currentText().toStdString())->getNodes());
        GeoLib::AABB const aabb(nodes.begin(), nodes.end());
        auto minAABB = aabb.getMinPoint();
        auto maxAABB = aabb.getMaxPoint();

        // only extract bounding box parameters that have been edited (otherwise there will be rounding errors!)
        minAABB[0] = (aabb_edits[0]) ? this->xMinEdit->text().toDouble() : (minAABB[0]);
        maxAABB[0] = (aabb_edits[1]) ? this->xMaxEdit->text().toDouble() : (maxAABB[0]);
        minAABB[1] = (aabb_edits[2]) ? this->yMinEdit->text().toDouble() : (minAABB[1]);
        maxAABB[1] = (aabb_edits[3]) ? this->yMaxEdit->text().toDouble() : (maxAABB[1]);
        minAABB[2] = (aabb_edits[4]) ? this->zMinEdit->text().toDouble() : (minAABB[2]);
        maxAABB[2] = (aabb_edits[5]) ? this->zMaxEdit->text().toDouble() : (maxAABB[2]);
        std::vector<MathLib::Point3d> extent;
        extent.push_back(minAABB);
        extent.push_back(maxAABB);
        const GeoLib::AABB updated_aabb(extent.begin(), extent.end());
        ex.searchByBoundingBox(updated_aabb);
        anything_checked = true;
    }

    if (this->zeroVolumeCheckBox->isChecked())
    {
        ex.searchByContent();
        anything_checked = true;
    }

    if (anything_checked)
    {
        MeshLib::Mesh* new_mesh = MeshLib::removeElements(*msh, ex.getSearchedElementIDs(), this->newMeshNameEdit->text().toStdString());
        if (new_mesh)
            emit meshAdded(new_mesh);
        else
        {
            if (new_mesh == nullptr)
                OGSError::box("The current selection removes ALL mesh elements.\nPlease change the selection.");
            if (ex.getSearchedElementIDs().empty())
                OGSError::box("The current selection removes NO mesh elements.");
            delete new_mesh;
            return;
        }
    }
    else
    {
        OGSError::box("No condition set for elements to remove.");
        return;
    }

    this->done(QDialog::Accepted);
}
Example #5
0
void GeoMapper::advancedMapOnMesh(const MeshLib::Mesh* mesh, const std::string &new_geo_name)
{
	const std::vector<GeoLib::Point*> *points (this->_geo_objects.getPointVec(this->_geo_name));
	const std::vector<GeoLib::Polyline*> *org_lines (this->_geo_objects.getPolylineVec(this->_geo_name));

	const GeoLib::AABB<GeoLib::Point> aabb(points->begin(), points->end());
	const double eps = sqrt(std::numeric_limits<float>::epsilon()) *
		               sqrt( MathLib::sqrDist(aabb.getMinPoint(),aabb.getMaxPoint())) ;

	// copy geometry (and set z=0 for all points)
	unsigned nGeoPoints ( points->size() );
	std::vector<GeoLib::Point*> *new_points = new std::vector<GeoLib::Point*>(nGeoPoints);
	for (size_t i=0; i<nGeoPoints; ++i)
		(*new_points)[i] = new GeoLib::Point((*(*points)[i])[0],(*(*points)[i])[1],0.0);
	std::vector<GeoLib::Polyline*> *new_lines (copyPolylinesVector(this->_geo_objects.getPolylineVec(this->_geo_name), new_points));

	GeoLib::Grid<GeoLib::Point> grid(new_points->begin(), new_points->end());
	double max_segment_length (this->getMaxSegmentLength(*new_lines));
	max_segment_length *= max_segment_length; // squared so it can be compared to the squared distances calculated later
	
	const unsigned nMeshNodes ( mesh->getNNodes() );	
	std::vector<int> closest_geo_point(nMeshNodes); // index of closest geo point for each mesh node in (x,y)-plane
	std::vector<double> dist(nMeshNodes);  // distance between geo points and mesh nodes in (x,y)-plane
	for (size_t i=0; i<nMeshNodes; ++i)
	{
		const double zero_coords[3] = {(* mesh->getNode(i))[0], (* mesh->getNode(i))[1], 0.0};
		GeoLib::Point* pnt = grid.getNearestPoint(zero_coords);
		dist[i] = MathLib::sqrDist(pnt->getCoords(), zero_coords);
		closest_geo_point[i] = (dist[i]<=max_segment_length) ? getIndexInPntVec(pnt, new_points) : -1;
	}
	
	// store for each point the line segment to which it was added.
	const size_t nLines (new_lines->size());
	std::vector< std::vector<unsigned> > line_segment_map(nLines);
	for (std::size_t i=0; i<nLines; ++i)
	{
		line_segment_map[i] = std::vector<unsigned>((*new_lines)[i]->getNumberOfPoints(),0);
		std::iota(line_segment_map[i].begin(), line_segment_map[i].end(), 0);
	}

	for (std::size_t i=0; i<nMeshNodes; ++i)
	{
		// if mesh node too far away or exactly at point position
		if (closest_geo_point[i] == -1 || dist[i] < eps) continue; 

		const MeshLib::Node* node (mesh->getNode(i));
		for (std::size_t l=0; l<nLines; ++l)
		{
			// find relevant polylines
			if (!(*org_lines)[l]->isPointIDInPolyline(closest_geo_point[i])) continue;
			
			// find point position of closest geo point in original polyline
			GeoLib::Polyline* ply ((*org_lines)[l]);
			std::size_t nLinePnts ( ply->getNumberOfPoints() );
			std::size_t node_index_in_ply (0);
			for (node_index_in_ply=0; node_index_in_ply<nLinePnts; ++node_index_in_ply)
				if (ply->getPoint(node_index_in_ply) == (*points)[closest_geo_point[i]])
					break;
			const GeoLib::Point* geo_point (ply->getPoint(node_index_in_ply));

			// check if line segments connected to closest geo point intersect connected elements of current node
			const std::vector<MeshLib::Element*> elements (node->getElements());
			const std::size_t nElems = elements.size();
			for (std::size_t e=0; e<nElems; ++e)
			{
				const unsigned nEdges (elements[e]->getNEdges());
				unsigned intersection_count (0);

				for (unsigned n=0; n<nEdges; ++n)
				{
					if (intersection_count>1) break; //already two intersections

					const MeshLib::Element* line = elements[e]->getEdge(n);
					unsigned index_offset(0); // default: add to first line segment
					GeoLib::Point* intersection (NULL);
					if (node_index_in_ply>0) // test line segment before closest point
						intersection = calcIntersection(line->getNode(0), line->getNode(1), geo_point, ply->getPoint(node_index_in_ply-1));
					if (intersection == NULL && node_index_in_ply<(nLinePnts-1)) // test line segment after closest point
					{
						intersection = calcIntersection(line->getNode(0), line->getNode(1), geo_point, ply->getPoint(node_index_in_ply+1));
						index_offset = 1; // add to second segment
					}
					if (intersection)
					{
						intersection_count++;
						unsigned start_point_idx = static_cast<unsigned>(std::distance(line_segment_map[l].begin(), std::find_if(line_segment_map[l].begin(), line_segment_map[l].end(), [&node_index_in_ply, &index_offset](unsigned a){return a==node_index_in_ply+index_offset-1;})));
						unsigned end_point_idx   = static_cast<unsigned>(std::distance(line_segment_map[l].begin(), std::find_if(line_segment_map[l].begin(), line_segment_map[l].end(), [&node_index_in_ply, &index_offset](unsigned a){return a==node_index_in_ply+index_offset;})));
						std::size_t pos = getPointPosInLine((*new_lines)[l], start_point_idx, end_point_idx, intersection, eps);

						if (pos)
						{
							const std::size_t pnt_pos (new_points->size());
							new_points->push_back(intersection);
							(*new_lines)[l]->insertPoint(pos, pnt_pos);
							line_segment_map[l].insert(line_segment_map[l].begin()+pos, node_index_in_ply+index_offset-1);
						}
					}
				}
			}
		}
	}

	this->_geo_objects.addPointVec(new_points, const_cast<std::string&>(new_geo_name));
	std::vector<size_t> pnt_id_map = this->_geo_objects.getPointVecObj(new_geo_name)->getIDMap();
	for (std::size_t i=0; i<new_lines->size(); ++i)
		(*new_lines)[i]->updatePointIDs(pnt_id_map);
	this->_geo_objects.addPolylineVec(new_lines, new_geo_name);

	// map new geometry incl. additional point using the normal mapping method
	this->_geo_name = new_geo_name;
	this->mapOnMesh(mesh);
}