168 lines
3.4 KiB
C++
168 lines
3.4 KiB
C++
|
|
/*
|
||
|
|
* This file is part of libfmr
|
||
|
|
*
|
||
|
|
* File: Seg.cpp
|
||
|
|
* Author: Florian Heinz <fh@sysv.de>
|
||
|
|
*
|
||
|
|
* Created on September 9, 2016, 3:21 PM
|
||
|
|
|
||
|
|
//paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}]
|
||
|
|
//[TOC] [\tableofcontents]
|
||
|
|
|
||
|
|
[1] Implementation of the class ~Seg~
|
||
|
|
|
||
|
|
[TOC]
|
||
|
|
|
||
|
|
1 Overview
|
||
|
|
|
||
|
|
The class Seg represents a line segment constructed from a start and
|
||
|
|
end point.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "fmr_Seg.h"
|
||
|
|
|
||
|
|
using namespace fmr;
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
2 Construct from start and endpoint
|
||
|
|
|
||
|
|
*/
|
||
|
|
Seg::Seg(Point i2, Point f2) : i(i2), f(f2) {
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
3 ~transform~
|
||
|
|
|
||
|
|
Transform this segment according to the TransformationUnit
|
||
|
|
~tu~ at time fraction frac (in [0;1])
|
||
|
|
|
||
|
|
*/
|
||
|
|
Seg Seg::transform(TransformationUnit& tu, double frac) {
|
||
|
|
Point i2 = i.transform(tu, frac);
|
||
|
|
Point f2 = f.transform(tu, frac);
|
||
|
|
|
||
|
|
return Seg(i2, f2);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
4 ~rotate~
|
||
|
|
|
||
|
|
Rotate this segment around point ~center~ by ~angle~
|
||
|
|
|
||
|
|
*/
|
||
|
|
Seg Seg::rotate(Point center, double angle) {
|
||
|
|
return Seg(i.rotate(center, angle), f.rotate(center, angle));
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
5 ~operator+~
|
||
|
|
|
||
|
|
Translate this segment by vector ~p~
|
||
|
|
|
||
|
|
*/
|
||
|
|
Seg Seg::operator+(Point v) {
|
||
|
|
return Seg(i + v, f + v);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
6 ~sign~
|
||
|
|
|
||
|
|
Calculate the sign of this segment with point ~p~.
|
||
|
|
|
||
|
|
The result is:
|
||
|
|
<0 if point ~p~ is left of the segment
|
||
|
|
=0 if point ~p~ is on the segment
|
||
|
|
>0 if point ~p~ is right of the segment
|
||
|
|
|
||
|
|
*/
|
||
|
|
double Seg::sign(Point p) {
|
||
|
|
return ((p.x - f.x)*(i.y - f.y)-(p.y - f.y)*(i.x - f.x));
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
7 ~getAngle~
|
||
|
|
|
||
|
|
Calculates the angle of this line segment.
|
||
|
|
|
||
|
|
*/
|
||
|
|
double Seg::getAngle() {
|
||
|
|
double ret = atan2(f.y - i.y, f.x - i.x) + 2.5 * M_PI;
|
||
|
|
while (ret > 2 * M_PI) {
|
||
|
|
ret -= 2 * M_PI;
|
||
|
|
}
|
||
|
|
|
||
|
|
return 2 * M_PI - ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
8 ~near~
|
||
|
|
|
||
|
|
Test if the segment ~s2~ is near this segment within a specified
|
||
|
|
~tolerance~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool Seg::near(Seg& s2, double tolerance) {
|
||
|
|
double limit = (f-i).length()*tolerance;
|
||
|
|
return ((i-s2.i).length() < limit && (f-s2.f).length() < limit);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
9 ~calculateTransformation~
|
||
|
|
|
||
|
|
Try to find a TransformationUnit, which would transform this segment into
|
||
|
|
the given segment ~seg~ with rotation point ~center~ and a specified
|
||
|
|
~tolerance~. The first item of the pair (the bool) specifies, if the second
|
||
|
|
part is a valid TransformationUnit.
|
||
|
|
|
||
|
|
*/
|
||
|
|
std::pair<bool, TransformationUnit> Seg::calculateTransformation(Seg& seg,
|
||
|
|
Point center, double tolerance) {
|
||
|
|
double l1 = (f-i).length(), l2 = (seg.f - seg.i).length();
|
||
|
|
if (std::abs(l2 - l1) > l1*tolerance) {
|
||
|
|
// Length differs too much, no valid transformation can be found here
|
||
|
|
return std::pair<bool, TransformationUnit>(false, TransformationUnit());
|
||
|
|
}
|
||
|
|
|
||
|
|
// The length of the segments is within the tolerance, a valid
|
||
|
|
// transformation can always be found now
|
||
|
|
|
||
|
|
// Calculate the necessary rotation angle between ]-Pi;Pi]
|
||
|
|
double angle = getAngle() - seg.getAngle();
|
||
|
|
if (angle <= -M_PI)
|
||
|
|
angle += 2*M_PI;
|
||
|
|
else if (angle > M_PI)
|
||
|
|
angle -= 2*M_PI;
|
||
|
|
|
||
|
|
// Calculate the correct vector for the given center point
|
||
|
|
Point vector = seg.i - i.rotate(center, angle);
|
||
|
|
TransformationUnit tu(center, vector, angle);
|
||
|
|
|
||
|
|
return std::pair<bool, TransformationUnit>(true, tu);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
10 ~intersects~
|
||
|
|
|
||
|
|
Test, if this segment intersects with a given Segment ~seg~
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool Seg::intersects(Seg& seg) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
11 ~ToString~
|
||
|
|
|
||
|
|
Returns a string representation for this segment
|
||
|
|
|
||
|
|
*/
|
||
|
|
std::string Seg::ToString() {
|
||
|
|
std::string ret = "";
|
||
|
|
|
||
|
|
ret = "( " + i.ToString() + " " + f.ToString() + " )";
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|