/* * This file is part of libfmr * * File: FMRegion.cpp * Author: Florian Heinz * * 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 (([*])) : See SpatialAlgebra : (
)
: The center point of the rotation relative to the region : Initial displacement of the region : Linear displacement during the time interval : Initial rotation of the region : Rotation of the region during the time 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; }