From 840d8bfec86b92818ff7a8e6d5bd32c04e07aadd Mon Sep 17 00:00:00 2001 From: Karsten Rink <karsten.rink@ufz.de> Date: Tue, 10 Sep 2013 17:38:43 +0200 Subject: [PATCH] new points are now added to lines --- Gui/DataView/GeoMapper.cpp | 94 +++++++++++++++++++++++--------------- Gui/DataView/GeoMapper.h | 1 + 2 files changed, 59 insertions(+), 36 deletions(-) diff --git a/Gui/DataView/GeoMapper.cpp b/Gui/DataView/GeoMapper.cpp index 85fea45d661..e14622e54b6 100644 --- a/Gui/DataView/GeoMapper.cpp +++ b/Gui/DataView/GeoMapper.cpp @@ -17,6 +17,8 @@ #include "GeoMapper.h" +#include <numeric> + #include "Mesh.h" #include "Elements\Element.h" #include "Elements\Tri.h" @@ -87,13 +89,13 @@ std::vector<GeoLib::Polyline*>* copyPolylinesVector(const std::vector<GeoLib::Po void GeoMapper::advancedMapOnMesh(const MeshLib::Mesh* mesh) { - // copy points (and set z=0) + // copy geometry (and set z=0 for all points) 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 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); - 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()); @@ -118,6 +120,14 @@ void GeoMapper::advancedMapOnMesh(const MeshLib::Mesh* mesh) } const size_t nLines (new_lines->size()); + // stores for each new point the line segment to which it was added. + 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 (closest_geo_point[i] == -1) continue; // is mesh node theoretically close enough? @@ -131,13 +141,13 @@ void GeoMapper::advancedMapOnMesh(const MeshLib::Mesh* mesh) for (std::size_t l=0; l<nLines; ++l) { // find relevant polylines - if (!(*new_lines)[l]->isPointIDInPolyline(closest_geo_point[i])) continue; + if (!(*org_lines)[l]->isPointIDInPolyline(closest_geo_point[i])) continue; - GeoLib::Polyline* ply ((*new_lines)[l]); - const std::size_t nLinePoints (ply->getNumberOfPoints()); + 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<nLinePoints; ++node_index_in_ply) - if (ply->getPoint(node_index_in_ply) == (*new_points)[closest_geo_point[i]]) + 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)); @@ -156,23 +166,28 @@ void GeoMapper::advancedMapOnMesh(const MeshLib::Mesh* mesh) if (intersection_count>1) break; //already two intersections const MeshLib::Element* line = elements[e]->getEdge(n); - bool add_before_geo_point (true); // default: add in first segment + unsigned index_offset(0); // default: add to second 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<(nLinePoints-1)) // test line segment after closest point + 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)); - add_before_geo_point = false; // add in second segment + index_offset = 1; // add to second segment } if (intersection) // intersection found { intersection_count++; - const size_t pnt_pos (new_points->size()); - new_points->push_back(new GeoLib::Point(intersection->getCoords())); + std::size_t pos = insertPointInLine((*new_lines)[l], intersection, node_index_in_ply+index_offset-1, line_segment_map[l]); + if (pos) + { + const std::size_t pnt_pos (new_points->size()); + new_points->push_back(new GeoLib::Point(intersection->getCoords())); + (*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); + + } delete intersection; - //(*new_lines)[l]->insertPoint(x, pnt_pos); - //schnittpunkt in linie AN RICHTIGER STELLE einfügen (abstand von neuem punkt zu punkt davor und danach) } } } @@ -184,40 +199,48 @@ void GeoMapper::advancedMapOnMesh(const MeshLib::Mesh* mesh) this->_geo_objects.addPolylineVec(new_lines, name); } - GeoLib::Point* GeoMapper::calcIntersection(GeoLib::Point const*const p1, GeoLib::Point const*const p2, GeoLib::Point const*const q1, GeoLib::Point const*const q2) const { - double x1 = (*p1)[0], x2 = (*p2)[0], x3 = (*q1)[0], x4 = (*q2)[0]; - double y1 = (*p1)[1], y2 = (*p2)[1], y3 = (*q1)[1], y4 = (*q2)[1]; + const double x1 = (*p1)[0], x2 = (*p2)[0], x3 = (*q1)[0], x4 = (*q2)[0]; + const double y1 = (*p1)[1], y2 = (*p2)[1], y3 = (*q1)[1], y4 = (*q2)[1]; - double det = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); + const double det = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); if (fabs(det) < std::numeric_limits<double>::epsilon()) return NULL; - // Get the x and y - double pre = (x1*y2 - y1*x2); - double post = (x3*y4 - y3*x4); - double x = ( pre * (x3 - x4) - (x1 - x2) * post ) / det; - double y = ( pre * (y3 - y4) - (y1 - y2) * post ) / det; + const double pre = (x1*y2 - y1*x2); + const double post = (x3*y4 - y3*x4); + const double x = ( pre * (x3 - x4) - (x1 - x2) * post ) / det; + const double y = ( pre * (y3 - y4) - (y1 - y2) * post ) / det; // Check if the x and y coordinates are within both line segments if (isPntInBoundingBox(x1,y1,x2,y2,x,y) && isPntInBoundingBox(x3,y3,x4,y4,x,y)) { - double denom (fabs(x2-x1) + (*p1)[2]); + const double denom (fabs(x2-x1) + (*p1)[2]); if (denom==0) return NULL; return new GeoLib::Point(x, y, fabs(fabs(x-x1)*fabs((*p2)[2]-(*p1)[2])/denom)); } return NULL; } -bool GeoMapper::isNodeOnLine(GeoLib::Point const*const p1, GeoLib::Point const*const q1, GeoLib::Point const*const q2) const +std::size_t GeoMapper::insertPointInLine(GeoLib::Polyline const*const line, GeoLib::Point const*const point, unsigned line_segment, const std::vector<unsigned> &line_segment_map) const { - double x = (*p1)[0], x1 = (*q1)[0], x2 = (*q2)[0]; - double y = (*p1)[1], y1 = (*q1)[1], y2 = (*q2)[1]; - - double det = (x1 - x2) * (y1 - y2) - (y1 - y2) * (x - x2); - if (fabs(det) < std::numeric_limits<double>::epsilon() && isPntInBoundingBox(x1,y1,x2,y2,x,y)) - return true; - return false; + const std::size_t nPoints (line->getNumberOfPoints()); + const GeoLib::Point* start (line->getPoint(line_segment)); + const double max_dist = MathLib::sqrDist(point, start); + bool line_segment_found (false); + for (std::size_t i=0; i<nPoints; ++i) + { + if (line_segment_found && line_segment_map[i]>line_segment) + return i; + if (line_segment_map[i]==line_segment) + { + line_segment_found = true; + if (MathLib::sqrDist(point, line->getPoint(i)) < std::numeric_limits<double>::epsilon()) return 0; // don't insert point + if (MathLib::sqrDist(start, line->getPoint(i))>max_dist) + return i; + } + } + return 0; // this should not happen! } bool GeoMapper::isPntInBoundingBox(double ax, double ay, double bx, double by, double px, double py) const @@ -234,13 +257,12 @@ double GeoMapper::getMaxSegmentLength(const std::vector<GeoLib::Polyline*> &line const std::size_t nPlys ( lines.size() ); for (size_t i=0; i<nPlys; ++i) { - double dist(0); - GeoLib::Polyline* line = lines[i]; - std::size_t nPlyPoints = line->getNumberOfPoints(); + const GeoLib::Polyline* line = lines[i]; + const std::size_t nPlyPoints = line->getNumberOfPoints(); double old_length (0); for (size_t j=1; j<nPlyPoints; ++j) { - dist = (line->getLength(j)-old_length); + double dist = (line->getLength(j)-old_length); old_length = line->getLength(j); if (dist>max_segment_length) max_segment_length=dist; diff --git a/Gui/DataView/GeoMapper.h b/Gui/DataView/GeoMapper.h index faa30f1dda5..4864acf9f6b 100644 --- a/Gui/DataView/GeoMapper.h +++ b/Gui/DataView/GeoMapper.h @@ -56,6 +56,7 @@ private: GeoLib::Point* calcIntersection(GeoLib::Point const*const p1, GeoLib::Point const*const p2, GeoLib::Point const*const q1, GeoLib::Point const*const q2) const; bool isNodeOnLine(GeoLib::Point const*const p1, GeoLib::Point const*const q1, GeoLib::Point const*const q2) const; bool isPntInBoundingBox(double ax, double ay, double bx, double by, double px, double py) const; + std::size_t insertPointInLine(GeoLib::Polyline const*const line, GeoLib::Point const*const point, unsigned line_segment, const std::vector<unsigned> &line_segment_map) const; GeoLib::GEOObjects& _geo_objects; const std::string& _geo_name; -- GitLab