| 148 | } |
| 149 | |
| 150 | PolygonSegment Polygon::findClosestSegment(const Transform::UnitVector& position) |
| 151 | { |
| 152 | const Transform::UnitVector p3 = position.to<Transform::Units::SceneUnits>(); |
| 153 | const auto distanceLineFromPoint = [](const Transform::UnitVector& point, |
| 154 | const Transform::UnitVector& lineP1, |
| 155 | const Transform::UnitVector& lineP2) { |
| 156 | Transform::UnitVector lineDiff = lineP2 - lineP1; |
| 157 | if (lineDiff.x == 0 && lineDiff.y == 0) |
| 158 | { |
| 159 | lineDiff = point - lineP1; |
| 160 | return sqrt(lineDiff.x * lineDiff.x + lineDiff.y * lineDiff.y); |
| 161 | } |
| 162 | |
| 163 | const double t |
| 164 | = ((point.x - lineP1.x) * lineDiff.x + (point.y - lineP1.y) * lineDiff.y) |
| 165 | / (lineDiff.x * lineDiff.x + lineDiff.y * lineDiff.y); |
| 166 | |
| 167 | if (t < 0) |
| 168 | { |
| 169 | // point is nearest to the first point i.e x1 and y1 |
| 170 | lineDiff = point - lineP1; |
| 171 | } |
| 172 | else if (t > 1) |
| 173 | { |
| 174 | // point is nearest to the end point i.e x2 and y2 |
| 175 | lineDiff = point - lineP2; |
| 176 | } |
| 177 | else |
| 178 | { |
| 179 | // if perpendicular line intersect the line segment. |
| 180 | lineDiff.x = point.x - (lineP1.x + t * lineDiff.x); |
| 181 | lineDiff.y = point.y - (lineP1.y + t * lineDiff.y); |
| 182 | } |
| 183 | |
| 184 | // returning shortest distance |
| 185 | return sqrt(lineDiff.x * lineDiff.x + lineDiff.y * lineDiff.y); |
| 186 | }; |
| 187 | double shortestDistance = -1; |
| 188 | std::size_t shortestIndex = 0; |
| 189 | for (std::size_t i = 0, j = getAllPoints().size() - 1; i < getAllPoints().size(); |
| 190 | j = i++) |
| 191 | { |
| 192 | const double currentDistance |
| 193 | = distanceLineFromPoint(p3, this->get(i), this->get(j)); |
| 194 | if (shortestDistance == -1 || currentDistance < shortestDistance) |
| 195 | { |
| 196 | shortestDistance = currentDistance; |
| 197 | shortestIndex = i; |
| 198 | } |
| 199 | } |
| 200 | return this->getSegment(shortestIndex); |
| 201 | } |
| 202 | |
| 203 | std::optional<PolygonSegment> Polygon::getSegmentContainingPoint( |
| 204 | const Transform::UnitVector& position, const double tolerance) |
nothing calls this directly
no test coverage detected