Files
secondo/Javagui/viewer/hoese/algebras/fixedmregion/FMRegion.java
2026-01-23 17:03:45 +08:00

283 lines
8.1 KiB
Java

package viewer.hoese.algebras.fixedmregion;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* Represents a Fixed Moving Region.
*
* This class represents a Fixed Moving Region. This is a region of fixed
* shape, which moves and rotates over one or more given time intervals.
*
* @author Florian Heinz <fh@sysv.de>
*/
public class FMRegion {
/** Shape of the region. */
private Region region;
/** One or more transformation units, which describe the movement. */
private List<FMRegionTrans> transformations = new LinkedList();
/** The moving segments calculated from region and transformations. */
private List<FMSeg> fmsegs = new LinkedList();
/** Start and end of the time interval. */
private Double start, end;
/**
* Creates an empty FMRegion.
*/
public FMRegion() {
}
/**
* Constructs an FMRegion from a given region.
* No transformation unit is initially added.
*
* @param region Shape of the Fixed Moving Region
*/
public FMRegion(Region region) {
this.region = region;
}
/**
* Get the shape of this Fixed Moving Region.
*
* @return Shape of this Fixed Moving Region
*/
public Region getRegion() {
return region;
}
/**
* Set the shape of this Fixed Moving Region.
*
* @param region New shape of this Fixed Moving Region
*/
public void setRegion(Region region) {
this.region = region;
}
/**
* Creates the Fixed Moving Segments for this FMRegion and the given
* transformation.
*
* @param transformation Transformation unit to create FMSegs for
*/
private void createFMSegs(FMRegionTrans transformation) {
if (region == null) {
return;
}
fmsegs.addAll(transformation.getFMSegs(region));
if (start == null || start > transformation.getStart()) {
start = transformation.getStart();
}
if (end == null || end < transformation.getEnd()) {
end = transformation.getEnd();
}
}
/**
* Clear all existing FMSegs and create new ones for the current data.
* Used if the underlying region or transformation units changed.
*
*/
public void renewFMSegs() {
fmsegs.clear(); // Remove all segments
start = end = null; // Clear the time interval boundaries
for (FMRegionTrans t : transformations) {
createFMSegs(t); // Create new fmsegs for all transformation units
}
}
/**
* Add a new transformation unit to this FMRegion.
*
* @param transformation New transformation unit
*/
public void addFMRegionTrans(FMRegionTrans transformation) {
transformations.add(transformation);
Collections.sort(transformations);
createFMSegs(transformation);
}
/**
*
* Add a new transformation unit from its parameters to this FMRegion.
*
* Adds a new transformation unit. This function also calculates the
* necessary initial translation and rotation, if this is not the first
* transformation unit.
*
* @param center Center point of rotation
* @param v Translation vector
* @param a Rotation angle
* @param duration Duration of the time interval
*/
public void addFMRegionTrans(Point center, Point v, double a, long duration) {
Point v0 = new Point(0, 0);
double a0 = 0;
double start = 0;
int nrtrans = transformations.size();
if (nrtrans > 0) {
FMRegionTrans t = transformations.get(nrtrans - 1);
v0 = t.getV0().add(t.getV());
a0 = t.getA0() + t.getA();
// Compensate change of center
Point dc = center.rotate(t.getCenter(), a0).sub(center);
v0 = v0.add(dc);
start = t.getEnd();
t.setRightClosed(false);
}
FMRegionTrans t = new FMRegionTrans(center, v0, v, a0, a, start, start + duration);
addFMRegionTrans(t);
}
/**
* Returns the overall start time of this FMRegion.
* This is the earliest instant of all transformation unit intervals.
*
* @return start time
*/
public double getStartTime() {
return start != null ? start : 0;
}
/**
* Returns the overall end time of this FMRegion.
* This is the latest instant of all transformation unit intervals.
*
* @return end time
*/
public double getEndTime() {
return end != null ? end : 0;
}
/**
* Calculate and return the bounding box of thie FMRegion.
* This is the bounding box, which is valid for all instants of this
* FMRegion.
*
* @return Bounding box of this FMRegion
*/
public Seg getBoundingBox() {
Seg bb = null;
for (FMRegionTrans t : getTransformations()) {
for (FMSeg fm : t.getFMSegs(region)) {
Seg bb2 = fm.getBoundingBox();
if (bb == null)
bb = bb2;
else {
if (bb2.s.x < bb.s.x)
bb.s.x = bb2.s.x;
if (bb2.e.x > bb.e.x)
bb.e.x = bb2.e.x;
if (bb2.s.y < bb.s.y)
bb.s.y = bb2.s.y;
if (bb2.e.y > bb.e.y)
bb.e.y = bb2.e.y;
}
}
}
return bb;
}
/**
* Create an FMRegion object from its Nested List representation
*
* @param nl Nested List representation of FMRegion
* @return FMRegion object
*/
public static FMRegion deserialize(NL nl) {
Region r = (Region) new Region().deserialize(nl.get(0));
FMRegion ret = new FMRegion(r);
NL trafos = nl.get(1);
for (int i = 0; i < trafos.size(); i++) {
FMRegionTrans t = FMRegionTrans.deserialize(trafos.get(i));
ret.addFMRegionTrans(t);
}
return ret;
}
/**
* Create a nested list representation from this FMRegion.
*
* @return Nested List representation of FMRegion
*/
public NL serialize() {
NL nl = new NL(), ret = nl;
nl.addNL(region.serialize());
nl = nl.nest();
for (FMRegionTrans t : transformations) {
nl.addNL(t.serialize());
}
return ret;
}
/**
* Get the calculated Fixed Moving Segments.
*
* @return Fixed Moving Segments
*/
public List<FMSeg> getFMSegs() {
return fmsegs;
}
/**
* Returns the last transformation of this FMRegion.
*
* @return Last transformation unit
*/
public FMRegionTrans getLastTransformation() {
int nrtrans = transformations.size();
if (nrtrans == 0)
return new FMRegionTrans();
FMRegionTrans t = transformations.get(nrtrans-1);
return t;
}
/**
* Returns a list of all transformation units.
*
* @return transformation units
*/
public List<FMRegionTrans> getTransformations() {
return transformations;
}
/**
* Sets the transformation units.
*
* @param transformations the transformation units to set
*/
public void setTransformations(List<FMRegionTrans> transformations) {
this.transformations = transformations;
}
/**
* Create a projection of this FMRegion at instant currentTime.
* The result is a Region object.
*
* @param currentTime Instant to project
* @return Resulting Region object
*/
Region project (double currentTime) {
Region ret = new Region();
FMRegionTrans trans = null;
for (FMRegionTrans t : transformations) {
if (t.getStart() < currentTime && t.getEnd() > currentTime) {
trans = t;
}
}
if (trans == null)
return null;
for (Face f : region.getFaces()) {
Face n = f.project(trans, currentTime);
ret.addFace(n);
}
return ret;
}
}