257 lines
6.5 KiB
C++
257 lines
6.5 KiB
C++
/*
|
|
* This file is part of libfmr
|
|
*
|
|
* File: FMRegion.cpp
|
|
* Author: Florian Heinz <fh@sysv.de>
|
|
*
|
|
* Created on September 6, 2016, 11:50 AM
|
|
|
|
//paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}]
|
|
//[TOC] [\tableofcontents]
|
|
|
|
[1] Class FMRegion
|
|
|
|
[TOC]
|
|
|
|
1 Overview
|
|
|
|
This class defines a moving and rotating region of fixed shape.
|
|
One or more ~transformation units~ define the movement over a
|
|
time interval.
|
|
|
|
*/
|
|
|
|
#include "fmr_FMRegion.h"
|
|
#include "fmr_TraversedAreaFactory.h"
|
|
|
|
using namespace fmr;
|
|
|
|
/*
|
|
2 ~FMRegion from RList~
|
|
|
|
This function creates an ~FMRegion~ from a RList.
|
|
|
|
2.1 List definition
|
|
|
|
(<region>(<transformation><transformation>[*]))
|
|
|
|
<region>: See SpatialAlgebra
|
|
|
|
<transformation>: (<center><v0><v><a0><a><interval>)
|
|
|
|
<center>: The center point of the rotation relative to the region
|
|
<v0>: Initial displacement of the region
|
|
<v>: Linear displacement during the time interval
|
|
<a0>: Initial rotation of the region
|
|
<a>: Rotation of the region during the time interval
|
|
<interval>: The time interval consisting of a start and end instant
|
|
|
|
2.2 Example
|
|
|
|
(
|
|
( \_! region !\_
|
|
( \_! face 1 !\_
|
|
( \_! main cycle !\_
|
|
(190 -30)
|
|
(110 -279)
|
|
(342 -156)
|
|
(162 -216) ) ) )
|
|
( \_! transformation units !\_
|
|
( \_! transformation unit 1 !\_
|
|
(185 -164) \_! center !\_
|
|
(0 0) \_! v0 !\_
|
|
(471 482) \_! v !\_
|
|
0 \_! a0 !\_
|
|
8 \_! a !\_
|
|
\_! interval !\_
|
|
("1970-01-01-01:00:00" "1970-01-01-01:08:20" TRUE FALSE ) )
|
|
( \_! transformation unit 2 !\_
|
|
(112 -274) \_! center !\_
|
|
(655 519) \_! v0 !\_
|
|
(638 -517) \_! v !\_
|
|
8 \_! a0 !\_
|
|
5 \_! a !\_
|
|
\_! interval !\_
|
|
("1970-01-01-01:08:20" "1970-01-01-01:16:40" TRUE TRUE ) ) ) )
|
|
|
|
*/
|
|
FMRegion::FMRegion(RList& l) {
|
|
region = Region(l[0]);
|
|
RList& tus = l[1];
|
|
for (int i = 0; i < tus.size(); i++) {
|
|
trafos.push_back(TransformationUnit(tus[i]));
|
|
}
|
|
}
|
|
|
|
/*
|
|
3 ~FMRegion~ from region and transformationunit
|
|
|
|
Creates an ~FMRegion~ from ~region~ and a first transformation unit ~tu~
|
|
|
|
*/
|
|
|
|
FMRegion::FMRegion(Region region, TransformationUnit tu) : region(region) {
|
|
trafos.push_back(tu);
|
|
}
|
|
|
|
/*
|
|
4 ~findTransformationUnit~
|
|
|
|
Find the transformation unit, which is defined at instant ~time~.
|
|
|
|
*/
|
|
TransformationUnit* FMRegion::findTransformationUnit (double time) {
|
|
for (int i = 0; i < trafos.size(); i++) {
|
|
TransformationUnit *tu = &trafos[i];
|
|
if ((tu->iv.start < time && tu->iv.end > time) ||
|
|
(tu->iv.start == time && tu->iv.lc) ||
|
|
(tu->iv.end == time && tu->iv.rc))
|
|
return tu;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
5 ~traversedArea~
|
|
|
|
Calculate the traversed area of this ~fmregion~
|
|
The result is of type ~CRegion~, since the line segments are curved
|
|
in general.
|
|
The actual calculations are performed in TraversedAreaFactory.cpp
|
|
|
|
*/
|
|
CRegion FMRegion::traversedArea() {
|
|
return fmr::traversedArea(*this);
|
|
}
|
|
|
|
/*
|
|
5.1 ~normalize~
|
|
|
|
Normalize this ~fmregion~. This means, that the y component of the
|
|
translation vector is set to 0. The object is rotated accordingly.
|
|
This only works with a single transformation unit.
|
|
|
|
*/
|
|
FMRegion FMRegion::normalize() {
|
|
TransformationUnit tu = trafos[0];
|
|
TransformationUnit tu2;
|
|
tu2.c = tu.c;
|
|
tu2.v0 = Point(0, 0);
|
|
tu2.v = Point(0, 0);
|
|
tu2.a0 = 0;
|
|
tu2.a = -tu.v.angle();
|
|
region = region.transform(tu2, 1.0);
|
|
trafos[0].v = Point(tu.v.length(), 0);
|
|
|
|
return *this;
|
|
}
|
|
|
|
/*
|
|
6 ~atinstant~
|
|
|
|
Calculates the projection of an ~fmregion~ to a ~region~ for the given
|
|
instant ~time~.
|
|
|
|
*/
|
|
Region FMRegion::atinstant (double time) {
|
|
TransformationUnit* tu = findTransformationUnit(time);
|
|
if (tu == NULL)
|
|
return Region();
|
|
|
|
return region.transform(*tu, tu->iv.getFrac(time));
|
|
}
|
|
|
|
/*
|
|
7 ~boundingBox~
|
|
|
|
Calculates the bounding box of this FMRegion. This is not necessarily a minimal
|
|
bounding box, but it is guaranteed that no part of the fmregion is outside at
|
|
any instant.
|
|
|
|
*/
|
|
BoundingBox FMRegion::boundingBox () {
|
|
BoundingBox bb;
|
|
for (unsigned int nrtrafo = 0; nrtrafo < trafos.size(); nrtrafo++) {
|
|
// Iterate over all transformation units
|
|
TransformationUnit& tu = trafos[nrtrafo];
|
|
Point p;
|
|
double dist = NAN;
|
|
// Find the point with the greatest distance from the center point of
|
|
// the rotation
|
|
for (unsigned int nrface = 0; nrface < region.faces.size(); nrface++) {
|
|
Face& f = region.faces[nrface];
|
|
for (unsigned int nrseg = 0; nrseg < f.segs.size(); nrseg++) {
|
|
Point p2 = f.segs[nrseg].i;
|
|
if (isnan(dist) || tu.c.distance(p2) > dist) {
|
|
dist = tu.c.distance(p2);
|
|
p = p2;
|
|
}
|
|
}
|
|
}
|
|
// Take the bounding box of the translation vector and add the distance
|
|
// of the point determined above from the center point to each
|
|
// direction.
|
|
Point start = tu.c + tu.v0;
|
|
Point end = start + tu.v;
|
|
double x1 = std::min(start.x, end.x) - dist;
|
|
double y1 = std::min(start.y, end.y) - dist;
|
|
double x2 = std::max(start.x, end.x) + dist;
|
|
double y2 = std::max(start.y, end.y) + dist;
|
|
|
|
// Enlarge the previous bounding box accordingly
|
|
bb.update(Point(x1, y1));
|
|
bb.update(Point(x2, y2));
|
|
}
|
|
|
|
return bb;
|
|
}
|
|
|
|
/*
|
|
8 ~setCenter~
|
|
|
|
Change the center of the movement. Start and end position of the movement
|
|
remains unchanged, but the path during the movement will differ.
|
|
|
|
*/
|
|
void FMRegion::setCenter(Point& nc) {
|
|
for (unsigned int i = 0; i < trafos.size(); i++) {
|
|
trafos[i].setCenter(nc);
|
|
}
|
|
}
|
|
|
|
/*
|
|
9 ~ToString~
|
|
|
|
Returns a string representation of this object
|
|
|
|
*/
|
|
std::string FMRegion::ToString() {
|
|
std::stringstream ss;
|
|
|
|
ss << "( " << region.ToString() << "\n";
|
|
for (int i = 0; i < trafos.size(); i++) {
|
|
ss << trafos[i].ToString() << "\n";
|
|
}
|
|
ss << ")";
|
|
return ss.str();
|
|
}
|
|
|
|
/*
|
|
10 ~toRList~
|
|
|
|
Returns an ~RList~ representation of this object
|
|
|
|
*/
|
|
RList FMRegion::toRList() {
|
|
RList ret;
|
|
|
|
ret.append(region.toRList());
|
|
RList& tr = ret.nest();
|
|
for (int i = 0; i < trafos.size(); i++) {
|
|
tr.append(trafos[i].toRList());
|
|
}
|
|
|
|
return ret;
|
|
}
|