2169 lines
58 KiB
Java
2169 lines
58 KiB
Java
//This file is part of SECONDO.
|
|
|
|
//Copyright (C) 2004, University in Hagen, Department of Computer Science,
|
|
//Database Systems for New Applications.
|
|
|
|
//SECONDO is free software; you can redistribute it and/or modify
|
|
//it under the terms of the GNU General Public License as published by
|
|
//the Free Software Foundation; either version 2 of the License, or
|
|
//(at your option) any later version.
|
|
|
|
//SECONDO is distributed in the hope that it will be useful,
|
|
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
//GNU General Public License for more details.
|
|
|
|
//You should have received a copy of the GNU General Public License
|
|
//along with SECONDO; if not, write to the Free Software
|
|
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
package fuzzyobjects.composite;
|
|
|
|
import fuzzyobjects.basic.*;
|
|
import fuzzyobjects.simple.*;
|
|
import java.util.Vector;
|
|
import sj.lang.ListExpr;
|
|
import java.io.*;
|
|
/**
|
|
* this class provides a implementation of fuzzy regions
|
|
* in the X-triangulation
|
|
* @author Thomas Behr
|
|
*/
|
|
|
|
public class FRegion implements CompositeObject{
|
|
|
|
/** the factor of scale */
|
|
protected double SF; // factor of scale
|
|
|
|
/** the set of fuzzy triangles */
|
|
protected SortedObjects fTs; // the fuzzy triangles
|
|
|
|
/** the Bounding Box */
|
|
protected BoundingBox BB = new BoundingBox();
|
|
|
|
/** returns the bounding box of this region */
|
|
public BoundingBox getBoundingBox(){ return BB; }
|
|
|
|
/** returns the number of containing triangles */
|
|
public int getSize(){
|
|
return fTs.getSize();
|
|
}
|
|
|
|
/** returns the triangle at given position */
|
|
public fTriangle getTriangleAt(int index){
|
|
if(index<0 || index >=fTs.getSize())
|
|
return null;
|
|
return (fTriangle) fTs.get(index);
|
|
}
|
|
|
|
/* remove all containibng triangles */
|
|
public void clear(){
|
|
fTs.makeEmpty();
|
|
}
|
|
|
|
/** computes the boundinmg box of this region */
|
|
private void computeBoundingBox(){
|
|
if(fTs.isEmpty())
|
|
BB.setBox(0,0,0,0);
|
|
else{
|
|
SimpleObject FT = fTs.get(0);
|
|
int minX = FT.getMinX();
|
|
int minY = FT.getMinY();
|
|
int maxX = FT.getMaxX();
|
|
int maxY = FT.getMaxY();
|
|
int cX,cY;
|
|
for (int i=1;i<fTs.getSize();i++){
|
|
FT = fTs.get(i);
|
|
cX = FT.getMinX();
|
|
cY = FT.getMinY();
|
|
if(cX < minX)
|
|
minX = cX;
|
|
if(cY < minY)
|
|
minY = cY;
|
|
cX = FT.getMaxX();
|
|
cY = FT.getMaxY();
|
|
if(cX > maxX)
|
|
maxX = cX;
|
|
if(cY > maxY)
|
|
maxY = cY;
|
|
}
|
|
BB.setBox(minX,minY,maxX,maxY);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* creates a new FRegion with given factor of scale
|
|
*/
|
|
public FRegion(double scale){
|
|
fTs = new SortedObjects();
|
|
SF = scale;
|
|
}
|
|
|
|
/**
|
|
* creates a new fuzzy Region with factor of scale 1.0
|
|
*/
|
|
public FRegion() {
|
|
this(1.0);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* returns a readable representation of this FRegion
|
|
*/
|
|
public String toString(){
|
|
return "FRegion (SF="+SF+")\n"+fTs.toString();
|
|
}
|
|
|
|
/** returns the factor of scale */
|
|
public double getSF(){ return SF;}
|
|
|
|
/** return the dimension of a region, i.e. 2 */
|
|
public int getDim(){ return 2; }
|
|
|
|
/** set the factor of scale */
|
|
public boolean setSF(double SF){
|
|
if(SF>0){
|
|
this.SF=SF;
|
|
return true;
|
|
}
|
|
else return false;
|
|
}
|
|
|
|
/**
|
|
* add a new fuzzy triangle to this FRegion
|
|
* returns false if this FRegion allready contains
|
|
* a fTriangle whith same basic as fT
|
|
*/
|
|
public boolean add(fTriangle fT){
|
|
boolean first = fTs.isEmpty();
|
|
boolean ok = fTs.insert(fT.copy());
|
|
if(ok) { // update bounding box
|
|
if(!first){
|
|
int minX = BB.getMinX();
|
|
int minY = BB.getMinY();
|
|
int maxX = BB.getMaxX();
|
|
int maxY = BB.getMaxY();
|
|
if(minX>fT.getMinX())
|
|
minX = fT.getMinX();
|
|
if(minY>fT.getMinY())
|
|
minY = fT.getMinY();
|
|
if(maxX<fT.getMaxX())
|
|
maxX = fT.getMaxX();
|
|
if(maxY<fT.getMaxY())
|
|
maxY = fT.getMaxY();
|
|
BB.setBox(minX,minY,maxX,maxY);
|
|
}
|
|
else
|
|
BB.setBox(fT.getMinX(),fT.getMinY(),
|
|
fT.getMaxX(),fT.getMaxY());
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
/**
|
|
* updated a fTriangle containing in this FRegion
|
|
* returns false if this FRegion not contains a
|
|
* fTriangle whith same basic as fT
|
|
*/
|
|
public boolean update(fTriangle fT){
|
|
return fTs.update(fT.copy());
|
|
}
|
|
|
|
/**
|
|
* updated / added a fuzzy Triangle
|
|
* if this FRegion allready contains a fTriangle whith same
|
|
* basic as fT then it was updated
|
|
* else fT is added to this FRegion
|
|
*/
|
|
public void overwrite(fTriangle fT){
|
|
boolean first = fTs.isEmpty();
|
|
if(fT.getMaxZ()==0){
|
|
delete((BasicTriangle) fT.basic());
|
|
}
|
|
else{
|
|
if (!fTs.update(fT))
|
|
fTs.insert(fT);
|
|
if(!first){
|
|
int minX = BB.getMinX();
|
|
int minY = BB.getMinY();
|
|
int maxX = BB.getMaxX();
|
|
int maxY = BB.getMaxY();
|
|
if(minX>fT.getMinX())
|
|
minX = fT.getMinX();
|
|
if(minY>fT.getMinY())
|
|
minY = fT.getMinY();
|
|
if(maxX<fT.getMaxX())
|
|
maxX = fT.getMaxX();
|
|
if(maxY<fT.getMaxY())
|
|
maxY = fT.getMaxY();
|
|
BB.setBox(minX,minY,maxX,maxY);
|
|
}
|
|
else
|
|
BB.setBox(fT.getMinX(),fT.getMinY(),
|
|
fT.getMaxX(),fT.getMaxY());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* is this a valid FRegion,
|
|
* i.e. all containing fTriangles are valid and
|
|
* factor of scale is greater then 0
|
|
*/
|
|
public boolean isValid(){
|
|
boolean ok = SF>0;
|
|
return ok & fTs.allValid();
|
|
}
|
|
|
|
|
|
/**
|
|
* creates a new FTriangle and invokes
|
|
* <a href="#overwrite(fTriangle)"> overwrite(fTriangle) </A>
|
|
* if it is valid
|
|
*/
|
|
public boolean overwrite( int x1, int y1, double Z1,
|
|
int x2, int y2, double Z2,
|
|
int x3, int y3, double Z3 ){
|
|
|
|
fTriangle FT = new fTriangle(x1,y1,Z1,x2,y2,Z2,x3,y3,Z3);
|
|
if(Z1==0 & Z2==0 & Z3==0){
|
|
BasicPoint P1 = new BasicPoint(x1,y1);
|
|
BasicPoint P2 = new BasicPoint(x2,y2);
|
|
BasicPoint P3 = new BasicPoint(x3,y3);
|
|
delete(new BasicTriangle(P1,P2,P3));
|
|
return true;
|
|
}
|
|
else{
|
|
boolean result= FT.isValid();
|
|
if (result)
|
|
overwrite(FT);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* deletes the fTriangle whith basic BT from this FRegion
|
|
* returns false if this FRegion not contains a such fTriangle
|
|
*/
|
|
public boolean delete(BasicTriangle BT){
|
|
boolean ok = fTs.delete(BT);
|
|
if(ok & ( BT.getMinX()==BB.getMinX() |
|
|
BT.getMaxX()==BB.getMaxX() |
|
|
BT.getMinY()==BB.getMinY() |
|
|
BT.getMaxY()==BB.getMaxY() ) )
|
|
computeBoundingBox();
|
|
return ok;
|
|
}
|
|
|
|
/**
|
|
* is this FRegion equals to FR ?
|
|
*/
|
|
public boolean equals(FRegion FR){
|
|
boolean ok;
|
|
if(FR==null){
|
|
ok=false;
|
|
}
|
|
else if(this==FR) // the same reference
|
|
ok=true;
|
|
else
|
|
ok= SF == FR.SF && fTs.equals(FR.fTs) ;
|
|
return ok;
|
|
}
|
|
|
|
|
|
/** computes all membershipvalues on (x,y) */
|
|
|
|
public double[] ZRel(double x, double y) {
|
|
|
|
Vector tmp = new Vector();
|
|
Double Z;
|
|
BasicTriangle[] Bts = BasicTriangle.getTriangles(x,y);
|
|
|
|
fTriangle current;
|
|
for(int i=0;i<Bts.length;i++){
|
|
current = (fTriangle) fTs.search(Bts[i]);
|
|
if(current!=null){
|
|
Z = new Double(current.Zfkt(x,y));
|
|
if(!tmp.contains(Z))
|
|
tmp.add(Z);
|
|
}
|
|
else{
|
|
Z = new Double(0);
|
|
if(!tmp.contains(Z))
|
|
tmp.add(Z);
|
|
}
|
|
}
|
|
|
|
double[] result;
|
|
if(tmp.size()==0){
|
|
result=new double[1];
|
|
result[0] = 0;
|
|
}
|
|
else{
|
|
result = new double[tmp.size()];
|
|
for(int i=0;i<tmp.size();i++)
|
|
result[i] = ((Double)tmp.get(i)).doubleValue();
|
|
}
|
|
return result;
|
|
} // ZRel
|
|
|
|
|
|
/** computes all membershipvalues on BP */
|
|
public double[] ZRel(BasicPoint BP){
|
|
Vector tmp=new Vector(10);
|
|
BasicPoint[] Neightboors = BP.getNeightboors();
|
|
// find all pairs of connected Neightboors
|
|
|
|
for(int i=0;i<Neightboors.length-1;i++)
|
|
for(int j=i+1;j<Neightboors.length;j++)
|
|
if( Neightboors[i].neightbooring(Neightboors[j]))
|
|
tmp.add(new BasicTriangle(BP,Neightboors[i],
|
|
Neightboors[j]));
|
|
Vector tmpResult = new Vector();
|
|
fTriangle currentfT;
|
|
for(int k=0;k<Neightboors.length;k++){
|
|
currentfT = (fTriangle)
|
|
fTs.search((BasicTriangle) tmp.get(k));
|
|
if(currentfT!=null)
|
|
tmpResult.add(new Double(currentfT.Zfkt(BP)));
|
|
else
|
|
tmpResult.add(new Double(0));
|
|
}
|
|
|
|
double[] result = new double[tmpResult.size()];
|
|
for(int i=0;i<tmpResult.size();i++){
|
|
result[i] = ((Double) tmpResult.get(i)).doubleValue();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/** computes the maximal membershipvalue on BP */
|
|
public double maxZfkt(BasicPoint BP){
|
|
double[] tmp = ZRel(BP);
|
|
double result = 0;
|
|
for(int i=0;i<tmp.length;i++)
|
|
if(result<tmp[i]) result = tmp[i];
|
|
return result;
|
|
}
|
|
|
|
/** computes the membershipvalue by given basicelement */
|
|
public double Zfkt(BasicPoint BP, BasicTriangle BT){
|
|
double result = 0.0;
|
|
fTriangle FT = (fTriangle) fTs.search(BT);
|
|
if (FT!=null)
|
|
result= FT.Zfkt(BP);
|
|
return result;
|
|
}
|
|
|
|
/** computes the membership-value on (x,y)
|
|
* by given BasicTriangle
|
|
*/
|
|
public double Zfkt(double x, double y, BasicTriangle BT){
|
|
if (BT.contains(x,y)){
|
|
fTriangle FT = (fTriangle) fTs.search(BT);
|
|
if(FT!=null)
|
|
return FT.Zfkt(x,y);
|
|
else
|
|
return 0.0;
|
|
}
|
|
else return 0.0;
|
|
}
|
|
|
|
/** returns the mimimum membership-value on (x,y) */
|
|
public double minZfkt(double x, double y){
|
|
double[] cands = ZRel(x,y);
|
|
double min = cands[0];
|
|
for(int i=1;i<cands.length;i++)
|
|
if(cands[i]<min)
|
|
min = cands[i];
|
|
return min;
|
|
}
|
|
|
|
/** returns the maximum membership-value on (x,y) */
|
|
public double maxZfkt(double x, double y){
|
|
double[] cands = ZRel(x,y);
|
|
double max = cands[0];
|
|
for(int i=1;i<cands.length;i++)
|
|
if(cands[i]<max)
|
|
max = cands[i];
|
|
return max;
|
|
}
|
|
|
|
/** returns the middle membership-value on (x,y) */
|
|
public double midZfkt(double x, double y){
|
|
double[] cands = ZRel(x,y);
|
|
double sum = 0;
|
|
for(int i=0;i<cands.length;i++)
|
|
sum += cands[i];
|
|
return sum/cands.length;
|
|
}
|
|
|
|
/** computes all basicTriangles containing in this fRegion */
|
|
public BasicTriangle[] basics() {
|
|
BasicTriangle[] result = new BasicTriangle[fTs.getSize()];
|
|
if(! fTs.isEmpty()) {
|
|
for(int i=0;i<fTs.getSize();i++)
|
|
result[i]=(BasicTriangle)((fTriangle)fTs.get(i)).basic();
|
|
}
|
|
return result;
|
|
} // basics
|
|
|
|
/** computes the maximal membershipvalue */
|
|
public double maxZ(){
|
|
double max = 0.0;
|
|
double currentmax;
|
|
double Z1,Z2,Z3;
|
|
fTriangle current;
|
|
for(int i=0;i<fTs.getSize();i++){
|
|
current = (fTriangle) fTs.get(i);
|
|
Z1 = current.getZ1();
|
|
Z2 = current.getZ2();
|
|
Z3 = current.getZ3();
|
|
currentmax = ( Math.max(Z1,Math.max(Z2,Z3)));
|
|
if (max < currentmax)
|
|
max = currentmax;
|
|
}
|
|
return max;
|
|
} // maxZ
|
|
|
|
/** computes the minimal membershipvalue */
|
|
public double minZ(){
|
|
double min = 1.0;
|
|
if(fTs.getSize()==0)
|
|
min=0.0;
|
|
double currentmin;
|
|
double Z1,Z2,Z3;
|
|
fTriangle current;
|
|
for(int i=0;i<fTs.getSize();i++){
|
|
current = (fTriangle) fTs.get(i);
|
|
Z1 = current.getZ1();
|
|
Z2 = current.getZ2();
|
|
Z3 = current.getZ3();
|
|
currentmin = ( Math.min(Z1,Math.min(Z2,Z3)));
|
|
if (min > currentmin)
|
|
min = currentmin;
|
|
}
|
|
return min;
|
|
} // minZ
|
|
|
|
/** returns a copy of this FRegion */
|
|
public FRegion copy(){
|
|
FRegion C = new FRegion(SF);
|
|
C.fTs = fTs.copy();
|
|
C.BB = BB.copy();
|
|
return C;
|
|
}
|
|
|
|
/** contains this FRegion elements ? */
|
|
public boolean isEmpty(){
|
|
return fTs.isEmpty();
|
|
}
|
|
|
|
/*************************************************************
|
|
Operators
|
|
*************************************************************/
|
|
|
|
/** the operator union */
|
|
public FRegion union(FRegion With){
|
|
return operator(With,UNION);
|
|
}
|
|
|
|
/** the operator scaled union */
|
|
public FRegion scaledUnion(FRegion With){
|
|
FRegion result = operator(With,SCALEDUNION);
|
|
result.norm();
|
|
return result;
|
|
}
|
|
|
|
/** the operator intersection */
|
|
public FRegion intersection(FRegion With){
|
|
return operator(With,INTERSECTION);
|
|
}
|
|
|
|
/** the operator scaled intersection */
|
|
public FRegion scaledIntersection(FRegion With){
|
|
FRegion result = operator(With,SCALEDINTERSECTION);
|
|
result.norm();
|
|
return result;
|
|
}
|
|
|
|
/** the add-operator */
|
|
public FRegion add(FRegion With){
|
|
return operator(With,ADD);
|
|
}
|
|
|
|
/** the operator scaled add */
|
|
public FRegion scaledAdd(FRegion With){
|
|
FRegion result = operator(With,SCALEDADD);
|
|
result.norm();
|
|
return result;
|
|
}
|
|
|
|
/** the difference-operator */
|
|
public FRegion difference(FRegion With){
|
|
return operator(With,SUBTRACT);
|
|
}
|
|
|
|
/** the operator scaled difference */
|
|
public FRegion scaledDifference(FRegion With){
|
|
FRegion result = operator(With,SCALEDDIFFERENCE);
|
|
result.norm();
|
|
return result;
|
|
}
|
|
|
|
/** the alpha-cut of this FRegion */
|
|
public FRegion alphaCut(double alpha, boolean strong){
|
|
FRegion CutR = new FRegion(SF);
|
|
fTriangle Current;
|
|
boolean isValid;
|
|
double midZ;
|
|
|
|
for(int i=0; i<fTs.getSize(); i++){
|
|
Current = (fTriangle) fTs.get(i);
|
|
midZ = (Current.getZ1()+ Current.getZ2() +
|
|
Current.getZ3())/3;
|
|
if (strong)
|
|
isValid = midZ>alpha;
|
|
else
|
|
isValid = midZ>= alpha;
|
|
|
|
if(isValid)
|
|
CutR.fTs.insert(Current.copy());
|
|
}
|
|
CutR.computeBoundingBox();
|
|
return CutR;
|
|
}
|
|
|
|
/** computes the area of the basic from this FRegion */
|
|
public double basicArea(){
|
|
double a = fuzzyobjects.Params.a;
|
|
double b = fuzzyobjects.Params.b;
|
|
return (a*b/4)*fTs.getSize();
|
|
}
|
|
|
|
/** computes the surface of the 3d-structure of this FRegion */
|
|
public double area3D(){
|
|
double result =0;
|
|
for(int i=0;i<fTs.getSize();i++)
|
|
result += ((fTriangle)fTs.get(i)).area3D();
|
|
return result;
|
|
}
|
|
|
|
/** the weigthted area of this FRegion */
|
|
public double area(){
|
|
double result = 0;
|
|
for(int i=0;i<fTs.getSize();i++)
|
|
result += ((fTriangle)fTs.get(i)).volume();
|
|
return result;
|
|
}
|
|
|
|
/** how similar are 2 fregion in their basic */
|
|
public double basicSimilar(FRegion F2){
|
|
FRegion Funion = this.union(F2);
|
|
FRegion Fintersection = this.intersection(F2);
|
|
if (Funion.isEmpty())
|
|
return 1.0;
|
|
else
|
|
return Fintersection.basicArea() / Funion.basicArea();
|
|
}
|
|
|
|
/** how similar are 2 FRegions */
|
|
public double similar(FRegion F2){
|
|
FRegion Funion = this.union(F2);
|
|
FRegion Fintersection = this.intersection(F2);
|
|
if (Funion.isEmpty())
|
|
return 1.0;
|
|
else
|
|
return Fintersection.area() / Funion.area();
|
|
}
|
|
|
|
/**
|
|
* returns a sharp Fregion
|
|
* all membershipvalues are 1.0
|
|
*/
|
|
public FRegion sharp(){
|
|
FRegion result = new FRegion(1);
|
|
fTriangle CurrentTriangle;
|
|
for(int i=0;i<fTs.getSize();i++){
|
|
CurrentTriangle = new fTriangle( (BasicTriangle) ((fTriangle)
|
|
fTs.get(i)).basic(),1,1,1);
|
|
result.add(CurrentTriangle);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/** computes the boundary of this fRegion */
|
|
public FLine boundary(){
|
|
|
|
FLine result = new FLine(1);
|
|
BasicTriangle CurrentBT;
|
|
BasicTriangle[] Neightboors;
|
|
BasicSegment BS;
|
|
|
|
for(int i=0;i<fTs.getSize();i++){
|
|
CurrentBT = (BasicTriangle) ((fTriangle) fTs.get(i)).basic();
|
|
Neightboors = CurrentBT.getNeightboors();
|
|
for(int j=0;j<Neightboors.length;j++) {
|
|
if ( fTs.search(Neightboors[j])==null ) {
|
|
BS = CurrentBT.commonSegment(Neightboors[j]);
|
|
result.add(new fSegment(BS,1,1));
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* computes the maximal connected part of a fRegion whith
|
|
* given start location
|
|
*/
|
|
/*
|
|
private void getComponent(fTriangle FT, FRegion result){
|
|
BasicTriangle BT = (BasicTriangle) FT.basic();
|
|
if (result.fTs.getPos(BT)>0) return;
|
|
|
|
result.add(FT);
|
|
BasicTriangle[] Neightboors = BT.getNeightboors();
|
|
|
|
for (int i=0;i<Neightboors.length;i++) {
|
|
if(result.fTs.getPos(Neightboors[i])<0){ // not in result
|
|
fTriangle NB = (fTriangle) fTs.search(Neightboors[i]);
|
|
// in current Region ?
|
|
if(NB!=null){
|
|
getComponent(NB,result);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
private void getComponent(fTriangle FT, FRegion result){
|
|
Vector List = new Vector(fTs.getSize());
|
|
fTriangle Current;
|
|
boolean found;
|
|
fTriangle N;
|
|
BasicTriangle CurrentBasic;
|
|
BasicTriangle[] Neightboors;
|
|
BasicTriangle Next;
|
|
Current = FT;
|
|
do{
|
|
CurrentBasic = (BasicTriangle) Current.basic();
|
|
result.add(Current);
|
|
Neightboors = CurrentBasic.getNeightboors();
|
|
for(int i=0;i<Neightboors.length;i++){
|
|
// for all Neightboors
|
|
found=false;
|
|
for(int j=0;j<List.size();j++){
|
|
if(Neightboors[i].equals((BasicTriangle)List.get(j)))
|
|
found=true;
|
|
}
|
|
|
|
if(!found && result.fTs.search(Neightboors[i])!=null)
|
|
found = true;
|
|
|
|
if(!found && fTs.getPos(Neightboors[i])>=0)
|
|
List.add(Neightboors[i]);
|
|
|
|
}// for all Neightboors
|
|
|
|
if(List.size()>0){
|
|
Next = (BasicTriangle) List.get(0);
|
|
List.remove(0);
|
|
Current=(fTriangle) fTs.search(Next);
|
|
}
|
|
else
|
|
Current = null;
|
|
} while( Current!=null);
|
|
}
|
|
|
|
/** returns the connected components of this FRegion */
|
|
public FRegion[] faces(){
|
|
if(isEmpty()) return null;
|
|
Vector tmp = new Vector(); // for the faces ;
|
|
// use Vector hence number of faces is unknow
|
|
FRegion Copy = this.copy();
|
|
while( ! Copy.isEmpty()){
|
|
FRegion nextFace = new FRegion(SF);
|
|
fTriangle First = (fTriangle) Copy.fTs.get(0);
|
|
getComponent(First,nextFace);
|
|
tmp.add(nextFace);
|
|
Copy = Copy.difference(nextFace);
|
|
}
|
|
|
|
FRegion[] result = new FRegion[tmp.size()];
|
|
for(int i=0;i<tmp.size();i++)
|
|
result[i] = (FRegion) tmp.get(i);
|
|
|
|
return result;
|
|
}
|
|
|
|
/** the mid-operator */
|
|
public static FRegion mid(FRegion[] Regs){
|
|
|
|
if(Regs.length==0) return null;
|
|
FRegion result = new FRegion(1);
|
|
int[] current = new int[Regs.length];
|
|
int[] max = new int[Regs.length];
|
|
boolean[] ready = new boolean[Regs.length];
|
|
boolean allready = true;
|
|
|
|
// initialize the variables
|
|
for(int i=0;i<Regs.length;i++){
|
|
current[i]=0;
|
|
max[i]= Regs[i].fTs.getSize();
|
|
ready[i] = current[i]>=max[i];
|
|
if(!ready[i]) allready=false;
|
|
}
|
|
|
|
|
|
Vector allSmallest = new Vector(); // the smallest Triangles
|
|
Vector Numbers = new Vector(); // the positions in Regs
|
|
|
|
while(!allready){
|
|
allready=true;
|
|
allSmallest = new Vector();
|
|
Numbers = new Vector();
|
|
// search all smallest Triangles
|
|
fTriangle currentT;
|
|
BasicTriangle compareT;
|
|
for(int i=0;i<Regs.length;i++){
|
|
if(current[i]<max[i]) {
|
|
allready=false;
|
|
currentT = (fTriangle) Regs[i].fTs.get(current[i]);
|
|
if(allSmallest.size()==0) {
|
|
allSmallest.add(currentT);
|
|
Numbers.add(new Integer(i));
|
|
}
|
|
else {
|
|
compareT = (BasicTriangle)
|
|
((fTriangle) allSmallest.get(0)).basic();
|
|
int comp = currentT.basic().compareTo(compareT);
|
|
if(comp==0) { // a Triangle with smallest Basic
|
|
allSmallest.add(currentT);
|
|
Numbers.add(new Integer(i));
|
|
}
|
|
if(comp<0) { // new smallest Triangle
|
|
allSmallest = new Vector();
|
|
Numbers = new Vector();
|
|
allSmallest.add(currentT);
|
|
Numbers.add(new Integer(i));
|
|
}
|
|
// in the case comp>0 is nothing to do
|
|
} // not the first triangle
|
|
} // current Reg contains unprocessing triangle(s)
|
|
} // for all Regs
|
|
|
|
if(!allready){
|
|
double Z1=0,Z2=0,Z3=0;
|
|
BasicTriangle BT = (BasicTriangle) (
|
|
(fTriangle) allSmallest.get(0)).basic();
|
|
fTriangle CT;
|
|
for(int i=0;i<allSmallest.size();i++){
|
|
// update numbers
|
|
int c = ((Integer)Numbers.get(i)).intValue();
|
|
current[c]++;
|
|
CT = (fTriangle) allSmallest.get(i);
|
|
Z1 += CT.getZ1();
|
|
Z2 += CT.getZ2();
|
|
Z3 += CT.getZ3();
|
|
}
|
|
Z1 = Z1 / Regs.length;
|
|
Z2 = Z2 / Regs.length;
|
|
Z3 = Z3 / Regs.length;
|
|
result.fTs.insert( new fTriangle(BT,Z1,Z2,Z3));
|
|
}
|
|
|
|
} // while not all ready
|
|
result.computeBoundingBox();
|
|
return result;
|
|
}
|
|
|
|
|
|
/** the scaled-mid-operator */
|
|
public static FRegion scaledMid(FRegion[] Regs){
|
|
|
|
if(Regs.length==0) return null;
|
|
FRegion result = new FRegion(1);
|
|
int[] current = new int[Regs.length];
|
|
int[] max = new int[Regs.length];
|
|
boolean[] ready = new boolean[Regs.length];
|
|
boolean allready = true;
|
|
|
|
// initialize the variables
|
|
for(int i=0;i<Regs.length;i++){
|
|
current[i]=0;
|
|
max[i]= Regs[i].fTs.getSize();
|
|
ready[i] = current[i]<max[i];
|
|
if(!ready[i]) allready=false;
|
|
}
|
|
|
|
Vector allSmallest = new Vector(); // the smallest Triangles
|
|
Vector Numbers = new Vector(); // the positions in Regs
|
|
|
|
while(!allready){
|
|
allready=true;
|
|
allSmallest = new Vector();
|
|
Numbers = new Vector();
|
|
// search all smallest Triangles
|
|
fTriangle currentT;
|
|
BasicTriangle compareT;
|
|
for(int i=0;i<Regs.length;i++){
|
|
if(current[i]<max[i]) {
|
|
allready=false;
|
|
currentT = (fTriangle) Regs[i].fTs.get(current[i]);
|
|
if(allSmallest.size()==0) {
|
|
allSmallest.add(currentT);
|
|
Numbers.add(new Integer(i));
|
|
}
|
|
else {
|
|
compareT = (BasicTriangle) (
|
|
(fTriangle) allSmallest.get(0)).basic();
|
|
int comp = currentT.basic().compareTo(compareT);
|
|
if(comp==0) { // a Triangle with smallest Basic
|
|
allSmallest.add(currentT);
|
|
Numbers.add(new Integer(i));
|
|
}
|
|
if(comp<0) { // new smallest Triangle
|
|
allSmallest = new Vector();
|
|
Numbers = new Vector();
|
|
allSmallest.add(currentT);
|
|
Numbers.add(new Integer(i));
|
|
}
|
|
// in the case comp>0 is nothing to do
|
|
} // not the first triangle
|
|
} // current Reg contains unprocessing triangle(s)
|
|
} // for all Regs
|
|
|
|
if(!allready){
|
|
double Z1=0,Z2=0,Z3=0;
|
|
BasicTriangle BT = (BasicTriangle) ((fTriangle)
|
|
allSmallest.get(0)).basic();
|
|
fTriangle CT;
|
|
for(int i=0;i<allSmallest.size();i++){
|
|
// update numbers
|
|
int c = ((Integer)Numbers.get(i)).intValue();
|
|
CT = (fTriangle) allSmallest.get(i);
|
|
Z1 += CT.getZ1()*Regs[c].SF;
|
|
Z2 += CT.getZ2()*Regs[c].SF;
|
|
Z3 += CT.getZ3()*Regs[c].SF;
|
|
}
|
|
Z1 = Z1 / Regs.length;
|
|
Z2 = Z2 / Regs.length;
|
|
Z3 = Z3 / Regs.length;
|
|
result.fTs.insert( new fTriangle(BT,Z1,Z2,Z3));
|
|
}
|
|
|
|
} // while not all ready
|
|
result.norm();
|
|
result.computeBoundingBox();
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* returns the number of triangles containing in this
|
|
* fRegion having BP as cornerpoint
|
|
*/
|
|
public int numberOfTriangles(BasicPoint BP){
|
|
Vector tmp=new Vector(10);
|
|
// contains all Triangles connected with BP
|
|
BasicPoint[] Neightboors = BP.getNeightboors();
|
|
// find all pairs of connected Neightboors
|
|
|
|
for(int i=0;i<Neightboors.length-1;i++)
|
|
for(int j=i+1;j<Neightboors.length;j++)
|
|
if( Neightboors[i].neightbooring(Neightboors[j]))
|
|
tmp.add(new BasicTriangle(BP,Neightboors[i],
|
|
Neightboors[j]));
|
|
|
|
// try to find this triangles
|
|
int result=0;
|
|
BasicTriangle BT;
|
|
for(int k=0;k<tmp.size();k++){
|
|
BT = (BasicTriangle) tmp.get(k);
|
|
if( fTs.search(BT)!=null )
|
|
result++;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* returns the number of triangles containing in this FRegion
|
|
* having BS as side
|
|
*/
|
|
public int numberOfTriangles(BasicSegment BS){
|
|
BasicTriangle[] BTs = BS.getTriangles();
|
|
int result=0;
|
|
for(int i=0;i<BTs.length;i++)
|
|
if (fTs.search(BTs[i])!=null) result++;
|
|
|
|
return result;
|
|
}
|
|
|
|
/** is BS a segment on boundary of this FRegion ? */
|
|
public boolean onBoundary(BasicSegment BS){
|
|
return numberOfTriangles(BS)==1;
|
|
}
|
|
|
|
/** is BP on boundary of this fRegion ? */
|
|
public boolean onBoundary(BasicPoint BP){
|
|
// a Point is on a Boundary of a Region R <=>
|
|
// exists a Segment S : BP isendpoint of BP and S
|
|
// is on the Boundary of R
|
|
|
|
BasicPoint[] Neightboors = BP.getNeightboors();
|
|
BasicSegment BS;
|
|
boolean found=false;
|
|
|
|
for(int i=0;i<Neightboors.length&!found;i++){
|
|
BS = new BasicSegment(BP,Neightboors[i]);
|
|
found = onBoundary(BS);
|
|
}
|
|
return found;
|
|
}
|
|
|
|
|
|
/** returns commonLines which are not part of a common area */
|
|
public FLine commonLines(FRegion R2){
|
|
|
|
int max = fTs.getSize();
|
|
FLine result = new FLine();
|
|
fTriangle FT;
|
|
BasicTriangle BT;
|
|
BasicSegment[] Sides;
|
|
BasicTriangle[] BTs;
|
|
boolean CommonTriangle;
|
|
boolean here,inR2;
|
|
|
|
for(int i=0;i<max;i++){
|
|
FT = (fTriangle) fTs.get(i);
|
|
BT = (BasicTriangle) FT.basic();
|
|
Sides = BT.getSides();
|
|
for(int j=0;j<Sides.length;j++){
|
|
if(R2.contains(Sides[j])) { // else is nothing to do
|
|
BTs=Sides[j].getTriangles();
|
|
CommonTriangle=false;
|
|
for(int k=0;k<BTs.length;k++){
|
|
here = BTs[k].equals(BT) || this.contains(BTs[k]);
|
|
inR2 = R2.contains(BTs[k]);
|
|
if(here & inR2) // exists a common area
|
|
CommonTriangle=true;
|
|
}
|
|
if(!CommonTriangle)
|
|
result.add(new fSegment(Sides[j],1,1));
|
|
} //if
|
|
}// for
|
|
} // for
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
/** returns the common points which not are
|
|
* a part of a common segment
|
|
*/
|
|
public FPoint commonPoints(FRegion R2){
|
|
|
|
int max = fTs.getSize();
|
|
FPoint result = new FPoint();
|
|
fTriangle FT;
|
|
BasicTriangle BT;
|
|
BasicPoint[] Corners;
|
|
BasicSegment[] Segs;
|
|
boolean CommonSegment;
|
|
boolean here,inR2;
|
|
|
|
for(int i=0;i<max;i++){
|
|
FT = (fTriangle) fTs.get(i);
|
|
BT = (BasicTriangle) FT.basic();
|
|
Corners = BT.getBasicPoints();
|
|
for(int j=0;j<Corners.length;j++){
|
|
if(R2.contains(Corners[j])) { // else is nothing to do
|
|
Segs= BasicSegment.getSegments(Corners[j]);
|
|
CommonSegment=false;
|
|
for(int k=0;k<Segs.length;k++){
|
|
here = this.contains(Segs[k]);
|
|
inR2 = R2.contains(Segs[k]);
|
|
if(here & inR2) // exists a common area
|
|
CommonSegment=true;
|
|
}
|
|
if(!CommonSegment)
|
|
result.add(new fEPoint(Corners[j],1));
|
|
} //if
|
|
}// for
|
|
} // for
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
/**
|
|
* converts a fLine with propertys of a circled Simple path to a
|
|
* Simple Path
|
|
*/
|
|
private SimplePath convertToSimplePath(FLine L){
|
|
|
|
SortedObjects fSegs = L.getSortedObjects();
|
|
|
|
fSegment Current = (fSegment) fSegs.get(0);
|
|
BasicSegment CurrentB = (BasicSegment) Current.basic();
|
|
SimplePath result = new SimplePath();
|
|
result.extend(CurrentB.getEP1());
|
|
result.extend(CurrentB.getEP2());
|
|
|
|
do{
|
|
BasicPoint BP = result.getLastPoint();
|
|
BasicSegment[] ConnectedSegment=BasicSegment.getSegments(BP);
|
|
|
|
int j=-1;
|
|
for(int i=0;i<ConnectedSegment.length;i++){
|
|
BasicSegment BS = ConnectedSegment[i];
|
|
if( !BS.equals(CurrentB) && fSegs.search(BS)!=null )
|
|
j=i;
|
|
}
|
|
|
|
BasicPoint BP1,BP2;
|
|
BP1 = ConnectedSegment[j].getEP1();
|
|
BP2 = ConnectedSegment[j].getEP2();
|
|
if(BP1.equals(BP))
|
|
result.extend(BP2);
|
|
else
|
|
result.extend(BP1);
|
|
CurrentB= ConnectedSegment[j]; // explore the next segment
|
|
}
|
|
while(!result.isACircle());
|
|
|
|
return result;
|
|
}
|
|
|
|
/** splits a connected Line into SimplePaths */
|
|
private SimplePath[] splitLine(FLine L){
|
|
SimplePath[] result;
|
|
BasicPoint[] cuts = L.selfcuts();
|
|
if(cuts.length==0){
|
|
result = new SimplePath[1];
|
|
SimplePath P = convertToSimplePath(L);
|
|
result[0] = P;
|
|
return result;
|
|
}
|
|
else{
|
|
Vector tmp = new Vector();
|
|
// compute simple Path from a selfcut to another one
|
|
SortedObjects fSegs = L.getSortedObjects(); // the segments
|
|
|
|
// mark used segments
|
|
boolean[] used = new boolean[fSegs.getSize()];
|
|
for(int i=0;i<used.length;i++) // no segment is used
|
|
used[i] = false;
|
|
|
|
BasicSegment[] NextSegments; // the segments from a selfcut
|
|
int pos; // the pos of a segment in fSegs
|
|
for(int i=0;i<cuts.length;i++){ // from a selfcut
|
|
NextSegments = BasicSegment.getSegments(cuts[i]);
|
|
for(int j=0;j<NextSegments.length;j++){ //explore all Segs
|
|
pos = fSegs.getPos(NextSegments[j]);
|
|
if( pos>=0 && !used[pos] ) {
|
|
BasicSegment CurrentB = NextSegments[j];
|
|
SimplePath nextPath = new SimplePath();
|
|
nextPath.extend(cuts[i]);
|
|
if(CurrentB.getEP1().equals(cuts[i]))
|
|
nextPath.extend(CurrentB.getEP2());
|
|
else
|
|
nextPath.extend(CurrentB.getEP1());
|
|
used[pos] = true;
|
|
boolean ready = false;
|
|
BasicPoint La = nextPath.getLastPoint();
|
|
for(int s=0;s<cuts.length;s++)
|
|
if(La.equals(cuts[s]))
|
|
ready = true;
|
|
if(!ready) {
|
|
do{
|
|
BasicPoint BP = nextPath.getLastPoint();
|
|
BasicSegment[] ConnectedSegment;
|
|
ConnectedSegment = BasicSegment.getSegments(BP);
|
|
int k=-1;
|
|
int foundPos;
|
|
BasicSegment BS;
|
|
do {
|
|
k++;
|
|
BS = ConnectedSegment[k];
|
|
foundPos = fSegs.getPos(BS);
|
|
} while( BS.equals(CurrentB) || foundPos<0);
|
|
used[foundPos] = true;
|
|
BasicPoint BP1,BP2;
|
|
BP1 = ConnectedSegment[k].getEP1();
|
|
BP2 = ConnectedSegment[k].getEP2();
|
|
BasicPoint Last;
|
|
if(BP1.equals(BP))
|
|
Last = BP2;
|
|
else
|
|
Last = BP1;
|
|
nextPath.extend(Last);
|
|
// explore the next segment
|
|
CurrentB= ConnectedSegment[k];
|
|
for (int n=0;n<cuts.length;n++)
|
|
if(Last.equals(cuts[n]))
|
|
ready = true;
|
|
} while(!ready);
|
|
} // if(!ready)
|
|
tmp.add(nextPath);
|
|
} // if(!used && found)
|
|
} // for(each startsegment)
|
|
} // for each selfcut
|
|
|
|
// build circles from the Paths
|
|
Vector tmp2 = new Vector(); // contains the result
|
|
Vector tmp3 = new Vector(); // contains not circled path
|
|
|
|
for(int o=0;o<tmp.size();o++)
|
|
if(((SimplePath) tmp.get(o)).isACircle())
|
|
tmp2.add(tmp.get(o));
|
|
else
|
|
tmp3.add(tmp.get(o));
|
|
|
|
|
|
// mark all simple path as 'not used'
|
|
boolean[] usedPath= new boolean[tmp3.size()];
|
|
for(int o=0;o<usedPath.length;o++)
|
|
usedPath[o] = false;
|
|
|
|
|
|
SimplePath CurrentPath;
|
|
Vector Points;
|
|
for(int o=0;o<tmp3.size();o++){
|
|
if(!usedPath[o]){
|
|
CurrentPath = (SimplePath) tmp3.get(o);
|
|
Points = new Vector();
|
|
usedPath[o] = true;
|
|
BasicPoint First = CurrentPath.getFirstPoint();
|
|
BasicPoint Last = CurrentPath.getLastPoint();
|
|
Points.add(First);
|
|
Points.add(Last);
|
|
boolean ready=false;
|
|
|
|
while(!ready) {
|
|
// search a Path extending CurrentPath
|
|
SimplePath EPath=null;
|
|
BasicPoint F2= null;
|
|
BasicPoint L2= null;
|
|
boolean found = false;
|
|
|
|
for(int p=0;p<tmp3.size() & !found; p++){
|
|
if(!usedPath[p]){
|
|
EPath = (SimplePath) tmp3.get(p);
|
|
F2 = EPath.getFirstPoint();
|
|
L2 = EPath.getLastPoint();
|
|
if( F2.equals(Last) || L2.equals(Last) ){
|
|
found=true;
|
|
usedPath[p] = true;
|
|
}
|
|
}
|
|
}// for
|
|
|
|
// EPath is a Path extendend CurrentPath
|
|
if(L2.equals(Last)){
|
|
EPath.invert(); // flip the Path
|
|
BasicPoint H = L2;
|
|
L2 = F2;
|
|
F2 = H;
|
|
}
|
|
|
|
if(First.equals(L2)){
|
|
CurrentPath.extend(EPath);
|
|
tmp2.add(CurrentPath);
|
|
ready=true;
|
|
}
|
|
else{
|
|
// test for a circle
|
|
boolean circletest=false;
|
|
for(int q=1;q<Points.size() & !circletest;q++){
|
|
if(L2.equals((BasicPoint) Points.get(q)))
|
|
circletest=true;
|
|
} // for
|
|
if(circletest){
|
|
SimplePath Rest = CurrentPath.split(L2);
|
|
Rest.extend(EPath);
|
|
tmp2.add(Rest);
|
|
Last = CurrentPath.getLastPoint();
|
|
// update Points
|
|
int r=Points.size()-1;
|
|
BasicPoint L3 = (BasicPoint) Points.get(r);
|
|
while(!L3.equals(Last)){
|
|
Points.remove(r);
|
|
r--;
|
|
L3 = (BasicPoint) Points.get(r);
|
|
}
|
|
}
|
|
else{
|
|
CurrentPath.extend(EPath);
|
|
Last = L2;
|
|
Points.add(Last);
|
|
}
|
|
|
|
} // else (not a 'big' circle)
|
|
} // while !ready
|
|
} // Path not used
|
|
} // for all Paths
|
|
|
|
|
|
result = new SimplePath[tmp2.size()];
|
|
for(int r=0;r<result.length;r++)
|
|
result[r] = (SimplePath) tmp2.get(r);
|
|
return result;
|
|
} // not a simple circle
|
|
|
|
}
|
|
|
|
|
|
/** compute the simplePaths from the boundary
|
|
* of a connected FRegion
|
|
*/
|
|
private SimplePath[] computeSimplePathsOfAFace(FRegion F){
|
|
|
|
FLine Bound = F.boundary();
|
|
FLine[] BoundFaces = Bound.faces();
|
|
|
|
Vector tmp=new Vector(); // store founded SimplePaths
|
|
for(int i=0;i<BoundFaces.length;i++){
|
|
SimplePath[] tmp2 = splitLine(BoundFaces[i]);
|
|
for(int j=0;j<tmp2.length;j++){
|
|
tmp.add(tmp2[j]);
|
|
}
|
|
}
|
|
|
|
|
|
SimplePath[] result = new SimplePath[tmp.size()];
|
|
for(int j=0;j<tmp.size();j++)
|
|
result[j]=(SimplePath) tmp.get(j);
|
|
return result;
|
|
}
|
|
|
|
|
|
/** computes the holes of a FRegion */
|
|
public FRegion holes(){
|
|
|
|
FRegion result = new FRegion();
|
|
if(this.isEmpty())
|
|
return result;
|
|
|
|
FRegion[] Faces = this.faces();
|
|
for(int i=0;i<Faces.length;i++){
|
|
SimplePath[] Paths = computeSimplePathsOfAFace(Faces[i]);
|
|
for(int j=0;j<Paths.length;j++){
|
|
BasicTriangle BT = Paths[j].getAInnerTriangle();
|
|
if(BT!=null){
|
|
if(fTs.search(BT)==null) { // is a hole
|
|
BasicTriangle[] BTs = Paths[j].getEnclosedTriangles();
|
|
for(int k=0;k<BTs.length;k++)
|
|
result.add(new fTriangle(BTs[k],1,1,1));
|
|
} // if
|
|
}//if
|
|
} // for
|
|
} // for
|
|
|
|
FRegion S = this.sharp();
|
|
result = result.difference(S);
|
|
return result;
|
|
|
|
}
|
|
|
|
/** returns the boundary without holes */
|
|
public FLine contour(){
|
|
FLine B1 = this.boundary();
|
|
FLine B2 = this.holes().boundary();
|
|
return B1.difference(B2);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************
|
|
end of operators
|
|
*************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
* set the containing Friangles from R1 to the same
|
|
* trianglers as R2
|
|
*/
|
|
protected static void setFts(FRegion R1, FRegion R2){
|
|
R1.fTs = R2.fTs;
|
|
R1.BB = R2.BB;
|
|
}
|
|
|
|
/**
|
|
* process a single triangle for many oparators
|
|
*/
|
|
private void processElements(fTriangle F1, double scale1,
|
|
fTriangle F2, double scale2,
|
|
FRegion Goal,
|
|
int Operator){
|
|
|
|
// 1 input parameter can be null
|
|
// if both fTriangles not null, then they must
|
|
// have the same basic
|
|
if( F1==null & F2==null) return;
|
|
|
|
double Z1,Z2,Z3;
|
|
fTriangle newFT;
|
|
switch (Operator){
|
|
|
|
case UNION : { // the union of 2 regions ignoring SFs
|
|
if(F1==null)
|
|
Goal.fTs.insert(F2.copy());
|
|
else if(F2==null)
|
|
Goal.fTs.insert(F1.copy());
|
|
else { // both fTriangles are not null
|
|
Z1 = Math.max(F1.getZ1(),F2.getZ1());
|
|
Z2 = Math.max(F1.getZ2(),F2.getZ2());
|
|
Z3 = Math.max(F1.getZ3(),F2.getZ3());
|
|
newFT = new fTriangle((BasicTriangle)
|
|
F1.basic(),
|
|
Z1,Z2,Z3 );
|
|
Goal.fTs.insert(newFT);
|
|
} // else
|
|
}
|
|
break;
|
|
|
|
case INTERSECTION : {
|
|
if (F1==null | F2==null)
|
|
;
|
|
else { // both are not null
|
|
Z1 = Math.min(F1.getZ1(),F2.getZ1());
|
|
Z2 = Math.min(F1.getZ2(),F2.getZ2());
|
|
Z3 = Math.min(F1.getZ3(),F2.getZ3());
|
|
if(Z1+Z2+Z3>0){
|
|
newFT = new fTriangle((BasicTriangle)
|
|
F1.basic(),
|
|
Z1,Z2,Z3 );
|
|
Goal.fTs.insert(newFT);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ADD : {
|
|
if(F1==null)
|
|
Goal.fTs.insert(F2.copy());
|
|
else if(F2==null)
|
|
Goal.fTs.insert(F1.copy());
|
|
else { // both fTriangles are not null
|
|
Z1 = Math.min(1,F1.getZ1()+F2.getZ1());
|
|
Z2 = Math.min(1,F1.getZ2()+F2.getZ2());
|
|
Z3 = Math.min(1,F1.getZ3()+F2.getZ3());
|
|
newFT = new fTriangle((BasicTriangle)
|
|
F1.basic(),
|
|
Z1,Z2,Z3 );
|
|
Goal.fTs.insert(newFT);
|
|
} // else
|
|
}
|
|
break;
|
|
|
|
case SUBTRACT :{
|
|
if(F1 == null)
|
|
;
|
|
else if(F2==null)
|
|
Goal.fTs.insert(F1.copy());
|
|
else { // both not null
|
|
Z1 = Math.max(0,F1.getZ1()-F2.getZ1());
|
|
Z2 = Math.max(0,F1.getZ2()-F2.getZ2());
|
|
Z3 = Math.max(0,F1.getZ3()-F2.getZ3());
|
|
if ((Z1+Z2+Z3)>0) {
|
|
newFT = new fTriangle( (BasicTriangle)
|
|
F1.basic(),Z1,Z2,Z3);
|
|
Goal.fTs.insert(newFT);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SCALEDUNION :{
|
|
fTriangle newTriangle;
|
|
if (F1==null)
|
|
newTriangle = new fTriangle( (BasicTriangle)
|
|
F2.basic(),
|
|
F2.getZ1()*scale2,
|
|
F2.getZ2()*scale2,
|
|
F2.getZ3()*scale2 );
|
|
else if (F2==null)
|
|
newTriangle = new fTriangle( (BasicTriangle)
|
|
F1.basic(),
|
|
F1.getZ1()*scale1,
|
|
F1.getZ2()*scale1,
|
|
F1.getZ3()*scale1);
|
|
else {
|
|
Z1 = Math.max(F1.getZ1()*scale1,
|
|
F2.getZ1()*scale2);
|
|
Z2 = Math.max(F1.getZ2()*scale1,
|
|
F2.getZ2()*scale2);
|
|
Z3 = Math.max(F1.getZ3()*scale1,
|
|
F2.getZ3()*scale2);
|
|
newTriangle = new fTriangle( (BasicTriangle)
|
|
F1.basic(),
|
|
Z1,Z2,Z3);
|
|
} // else
|
|
Goal.add(newTriangle);
|
|
}
|
|
break; // scaled union
|
|
|
|
case SCALEDINTERSECTION :
|
|
if (F1==null || F2==null)
|
|
;
|
|
else {
|
|
Z1 = Math.min(F1.getZ1()*scale1,
|
|
F2.getZ1()*scale2);
|
|
Z2 = Math.min(F1.getZ2()*scale1,
|
|
F2.getZ2()*scale2);
|
|
Z3 = Math.min(F1.getZ3()*scale1,
|
|
F2.getZ3()*scale2);
|
|
Goal.add(new fTriangle( (BasicTriangle)
|
|
F1.basic(),
|
|
Z1,Z2,Z3));
|
|
}
|
|
break;
|
|
|
|
case SCALEDADD : {
|
|
if(F1==null)
|
|
Goal.add(new fTriangle( (BasicTriangle)
|
|
F2.basic(),
|
|
F2.getZ1()*scale2,
|
|
F2.getZ2()*scale2,
|
|
F2.getZ3()*scale2));
|
|
else if(F2==null)
|
|
Goal.add(new fTriangle( (BasicTriangle)
|
|
F1.basic(),
|
|
F1.getZ1()*scale1,
|
|
F1.getZ2()*scale1,
|
|
F1.getZ3()*scale1));
|
|
else {
|
|
Goal.add(new fTriangle( (BasicTriangle)
|
|
F1.basic(),
|
|
F1.getZ1()*scale1 +
|
|
F2.getZ1()*scale2 ,
|
|
F1.getZ2()*scale1 +
|
|
F2.getZ2()*scale2 ,
|
|
F1.getZ3()*scale1 +
|
|
F2.getZ3()*scale2 ));
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case SCALEDDIFFERENCE : {
|
|
if(F1==null)
|
|
Goal.add(new fTriangle( (BasicTriangle)
|
|
F2.basic(),
|
|
-F2.getZ1()*scale2,
|
|
-F2.getZ2()*scale2,
|
|
-F2.getZ3()*scale2));
|
|
else if(F2==null)
|
|
Goal.add(new fTriangle( (BasicTriangle)
|
|
F1.basic(),
|
|
F1.getZ1()*scale1,
|
|
F1.getZ2()*scale1,
|
|
F1.getZ3()*scale1));
|
|
else {
|
|
Goal.add(new fTriangle( (BasicTriangle)
|
|
F1.basic(),
|
|
F1.getZ1()*scale1 -
|
|
F2.getZ1()*scale2 ,
|
|
F1.getZ2()*scale1 -
|
|
F2.getZ2()*scale2 ,
|
|
F1.getZ3()*scale1 -
|
|
F2.getZ3()*scale2 ));
|
|
}
|
|
}
|
|
break;
|
|
default : System.err.println("operator not implemented");
|
|
} // switch
|
|
} // processElements
|
|
|
|
|
|
/** the 'template' for many operators */
|
|
protected FRegion operator(FRegion FR, int op){
|
|
// a kind of mergesort
|
|
|
|
int my = 0;
|
|
int fromFR = 0; // already processed
|
|
|
|
int maxMy = fTs.getSize(); // numbers of elements
|
|
int maxFromFR = FR.fTs.getSize();
|
|
FRegion result = new FRegion(1);
|
|
|
|
fTriangle myFirst=null; // the first unprocessed elements
|
|
fTriangle FRFirst=null;
|
|
|
|
if(maxMy>0)
|
|
myFirst = (fTriangle) fTs.get(0);
|
|
if(maxFromFR>0)
|
|
FRFirst = (fTriangle) FR.fTs.get(0);
|
|
|
|
if (maxMy >0 && maxFromFR>0){
|
|
myFirst = (fTriangle) fTs.get(my);
|
|
FRFirst = (fTriangle) FR.fTs.get(fromFR);
|
|
int compareResult;
|
|
while(my<maxMy && fromFR<maxFromFR){
|
|
// both sets have unprocessed elements
|
|
compareResult=myFirst.basic().compareTo(FRFirst.basic());
|
|
if(compareResult < 0) {
|
|
processElements(myFirst,SF,null,FR.SF,result,op);
|
|
my++;
|
|
if (my<maxMy)
|
|
myFirst = (fTriangle) fTs.get(my);
|
|
}
|
|
else if(compareResult > 0){
|
|
processElements(null,SF,FRFirst,FR.SF,result,op);
|
|
fromFR++;
|
|
if(fromFR<maxFromFR)
|
|
FRFirst = (fTriangle) FR.fTs.get(fromFR);
|
|
}
|
|
else { // elements have the same basic
|
|
processElements(myFirst,SF,FRFirst,FR.SF,result,op);
|
|
my++;
|
|
fromFR++;
|
|
if (my<maxMy)
|
|
myFirst = (fTriangle) fTs.get(my);
|
|
if (fromFR<maxFromFR)
|
|
FRFirst = (fTriangle) FR.fTs.get(fromFR);
|
|
}
|
|
} // while
|
|
} // if
|
|
|
|
// elements from one (or both) regions are processed
|
|
|
|
while(my < maxMy){ // this have still elements
|
|
processElements(myFirst,SF,null,FR.SF,result,op);
|
|
my++;
|
|
if (my<maxMy)
|
|
myFirst = (fTriangle) fTs.get(my);
|
|
}
|
|
|
|
while (fromFR < maxFromFR){ // FR have still elements
|
|
processElements(null,SF,FRFirst,FR.SF,result,op);
|
|
fromFR++;
|
|
if(fromFR<maxFromFR)
|
|
FRFirst = (fTriangle) FR.fTs.get(fromFR);
|
|
}
|
|
result.computeBoundingBox();
|
|
return result;
|
|
}
|
|
|
|
/** normalize this FRegion */
|
|
private void norm(){
|
|
|
|
if (isEmpty()) return; // nothing to do
|
|
|
|
// first compute Zmin and Zmax
|
|
double Zmin = 0;
|
|
double Zmax = 0;
|
|
fTriangle Current;
|
|
|
|
for (int i=0; i< fTs.getSize();i++){
|
|
Current = (fTriangle) fTs.get(i);
|
|
if(Current.getMaxZ()>Zmax)
|
|
Zmax = Current.getMaxZ();
|
|
if(Current.getMinZ()<Zmin)
|
|
Zmin = Current.getMinZ();
|
|
}
|
|
|
|
if(Zmin > 0) Zmin=0;
|
|
|
|
if(Zmax==0 & Zmin==0)
|
|
fTs.makeEmpty();
|
|
else{
|
|
double SFnew = Zmax - Zmin;
|
|
SortedObjects newfTs= new SortedObjects();
|
|
double Z1,Z2,Z3;
|
|
fTriangle fTnew;
|
|
|
|
for(int i=0;i<fTs.getSize();i++){
|
|
Current = (fTriangle) fTs.get(i);
|
|
Z1 = Current.getZ1();
|
|
Z2 = Current.getZ2();
|
|
Z3 = Current.getZ3();
|
|
fTnew = new fTriangle( (BasicTriangle) Current.basic(),
|
|
(Z1-Zmin)/SFnew ,
|
|
(Z2-Zmin)/SFnew,
|
|
(Z3-Zmin)/SFnew );
|
|
if (fTnew.getMaxZ() >0)
|
|
newfTs.insert(fTnew);
|
|
} // for
|
|
SF = SFnew*SF;
|
|
fTs = newfTs;
|
|
}
|
|
computeBoundingBox();
|
|
}
|
|
|
|
|
|
/** check wether this FRegions contains BP */
|
|
public boolean contains(BasicPoint BP){
|
|
return numberOfTriangles(BP)>0;
|
|
}
|
|
|
|
/** check wether this FRegion contains BS */
|
|
public boolean contains(BasicSegment BS){
|
|
return numberOfTriangles(BS)>0;
|
|
}
|
|
|
|
/** check wether this FRegion contains BT */
|
|
public boolean contains(BasicTriangle BT){
|
|
return fTs.search(BT)!=null;
|
|
}
|
|
|
|
/***********************************************************
|
|
* *
|
|
* Topology of the basic *
|
|
* *
|
|
***** ****************************************************/
|
|
|
|
|
|
|
|
/** this method is helping for basicTopolRelation */
|
|
private static void processTriangle(
|
|
BasicTriangle T,FRegion R1,FRegion R2,
|
|
M9Int goal){
|
|
BasicPoint[] BP = new BasicPoint[3];
|
|
boolean onR1,onR2,onBoundary1,onBoundary2;
|
|
|
|
// process points of minimum Triangle
|
|
BP[0] = T.getCP1();
|
|
BP[1] = T.getCP2();
|
|
BP[2] = T.getCP3();
|
|
|
|
for(int i=0;i<3;i++){
|
|
onBoundary1 = R1.onBoundary(BP[i]);
|
|
onBoundary2 = R2.onBoundary(BP[i]);
|
|
onR1 = R1.contains(BP[i]);
|
|
onR2 = R2.contains(BP[i]);
|
|
|
|
if(onR1 & onR2){ // else is nothing to do
|
|
if(onBoundary1)
|
|
if(onBoundary2)
|
|
goal.setValue(true,M9Int.BOUNDARY,M9Int.BOUNDARY);
|
|
else
|
|
goal.setValue(true,M9Int.BOUNDARY,M9Int.INTERIOR);
|
|
else
|
|
if(onBoundary2)
|
|
goal.setValue(true,M9Int.INTERIOR,M9Int.BOUNDARY);
|
|
else
|
|
goal.setValue(true,M9Int.INTERIOR,M9Int.INTERIOR);
|
|
} // if common Point
|
|
} // for
|
|
} // processTriangle
|
|
|
|
|
|
|
|
/** computes the 9-intersection-matrix for 2 fregions */
|
|
M9Int basicTopolRelation(FRegion R2){
|
|
|
|
M9Int result = new M9Int();
|
|
// this holds ever
|
|
result.setValue(true,M9Int.EXTERIOR,M9Int.EXTERIOR);
|
|
|
|
boolean ready=false; // all checked intersections are true
|
|
int currentThis=0;
|
|
int currentR2 = 0;
|
|
int maxThis = fTs.getSize();
|
|
int maxR2 = R2.fTs.getSize();
|
|
int compareResult;
|
|
fTriangle C1,C2;
|
|
BasicTriangle MinBasic;
|
|
fTriangle minT=null;
|
|
BasicPoint[] BP = new BasicPoint[3];
|
|
boolean onBoundary1,onBoundary2,
|
|
onThis,onR2;
|
|
|
|
while( (currentThis<maxThis) & (currentR2<maxR2) & !ready) {
|
|
|
|
C1 = (fTriangle) fTs.get(currentThis);
|
|
C2 = (fTriangle) R2.fTs.get(currentR2);
|
|
|
|
compareResult=(C1.basic().compareTo(C2.basic()));
|
|
|
|
if(compareResult<0){
|
|
result.setValue(true,M9Int.INTERIOR,M9Int.EXTERIOR);
|
|
currentThis++;
|
|
minT=C1;
|
|
}
|
|
if(compareResult>0){
|
|
result.setValue(true,M9Int.EXTERIOR,M9Int.INTERIOR);
|
|
currentR2++;
|
|
minT=C2;
|
|
}
|
|
if(compareResult==0){
|
|
currentThis++;
|
|
currentR2++;
|
|
minT=C1;
|
|
result.setValue(true,M9Int.INTERIOR,M9Int.INTERIOR);
|
|
}
|
|
processTriangle((BasicTriangle) minT.basic(),this,R2,result);
|
|
|
|
} // while
|
|
|
|
|
|
if( currentThis<maxThis){
|
|
result.setValue(true,M9Int.INTERIOR,M9Int.EXTERIOR);
|
|
while(currentThis<maxThis){
|
|
minT = (fTriangle)fTs.get(currentThis);
|
|
MinBasic = (BasicTriangle) minT.basic();
|
|
currentThis++;
|
|
processTriangle(MinBasic,this,R2,result);
|
|
}
|
|
}
|
|
|
|
if( currentR2<maxR2){
|
|
result.setValue(true,M9Int.EXTERIOR,M9Int.INTERIOR);
|
|
while(currentR2<maxR2){
|
|
minT = (fTriangle)R2.fTs.get(currentR2);
|
|
MinBasic = (BasicTriangle) minT.basic();
|
|
currentR2++;
|
|
processTriangle(MinBasic,this,R2,result);
|
|
} // while
|
|
} // if
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/** computes the topology for this region with another
|
|
* fuzzy object
|
|
*/
|
|
public M9Int basicTopolRelation(CompositeObject CO){
|
|
|
|
M9Int result;
|
|
if( (CO instanceof FPoint) | (CO instanceof FLine)) {
|
|
result = CO.basicTopolRelation(this);
|
|
result.makeSym();
|
|
return result;
|
|
}
|
|
if( CO instanceof FRegion)
|
|
return basicTopolRelation( (FRegion) CO);
|
|
return null;
|
|
}
|
|
|
|
|
|
/*****************************************************
|
|
* *
|
|
* topology on fuzzy objects *
|
|
* *
|
|
*****************************************************/
|
|
|
|
/**
|
|
* this function get membershipvalues and a cut-position
|
|
* for a given BasicSegment
|
|
* <br>
|
|
* <ul>
|
|
* <li> result[0] : the membership-value for the first
|
|
endpoint of the BasicSegment (maximum of all fSegments
|
|
* with the same basic as BS </li>
|
|
* <li> result[1] : the same for the second endpoint </li>
|
|
* <li> if the length of the result greater then 2 then
|
|
* exists two crossing fSgements in this region with same
|
|
* basic as BS.
|
|
* <ul>
|
|
* <li> result[2] where is the cross point </li>
|
|
* <li> result[3] the membershipvalue over the cross
|
|
* point </li>
|
|
* </ul>
|
|
* </li>
|
|
* </ul>
|
|
*/
|
|
double[] getValues(BasicSegment BS){
|
|
|
|
double[] result;
|
|
BasicTriangle[] BTs = BS.getTriangles(); // exact 2 Triangles
|
|
fTriangle FT1 = (fTriangle) fTs.search(BTs[0]);
|
|
fTriangle FT2 = (fTriangle) fTs.search(BTs[1]);
|
|
|
|
if( FT1==null || FT2==null){
|
|
result = new double[2];
|
|
if(FT1==null){
|
|
if(FT2==null){
|
|
result[0] = 0;
|
|
result[1] = 0;
|
|
}
|
|
else{ //FT2!=null
|
|
result[0] = FT2.Zfkt(BS.getEP1());
|
|
result[1] = FT2.Zfkt(BS.getEP2());
|
|
}
|
|
}
|
|
else{ // FT1!=null
|
|
result[0] = FT1.Zfkt(BS.getEP1());
|
|
result[1] = FT1.Zfkt(BS.getEP2());
|
|
}
|
|
}
|
|
else{ // both fTriangles exists
|
|
double Z1_1 = FT1.Zfkt(BS.getEP1());
|
|
double Z1_2 = FT1.Zfkt(BS.getEP2());
|
|
double Z2_1 = FT2.Zfkt(BS.getEP1());
|
|
double Z2_2 = FT2.Zfkt(BS.getEP2());
|
|
if( (Z1_1-Z2_1) * (Z1_2-Z2_2)>=0) { // no crossing
|
|
result = new double[2];
|
|
result[0] = Math.max(Z1_1,Z2_1);
|
|
result[1] = Math.max(Z1_2,Z2_2);
|
|
}
|
|
else{ // the segments are crossing
|
|
result = new double[4];
|
|
result[0] = Math.max(Z1_1,Z2_1);
|
|
result[1] = Math.max(Z1_2,Z2_2);
|
|
// compute the cross-position
|
|
double pos = (Z2_1-Z1_1) / (Z1_2-Z1_1-Z2_2+Z2_1);
|
|
double value = Z1_1 + pos*(Z1_2-Z1_1);
|
|
result[2] = pos;
|
|
result[3] = value;
|
|
}
|
|
} // else
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* returns the max value from both segments on given pos
|
|
* pos must be in [0,1]
|
|
*/
|
|
double getMaxValue(BasicSegment BS ,double pos){
|
|
|
|
if( (pos<0) || (pos >1))
|
|
return 0;
|
|
|
|
BasicTriangle[] BTs = BS.getTriangles(); // exact 2 Triangles
|
|
fTriangle FT1 = (fTriangle) fTs.search(BTs[0]);
|
|
fTriangle FT2 = (fTriangle) fTs.search(BTs[1]);
|
|
double Z1_1,Z1_2,Z2_1,Z2_2; // values on the endpoints
|
|
double V1,V2; //values on given Position
|
|
if(FT1==null){
|
|
Z1_1=0;
|
|
Z1_2=0;
|
|
}
|
|
else{
|
|
Z1_1 = FT1.Zfkt(BS.getEP1());
|
|
Z1_2 = FT1.Zfkt(BS.getEP2());
|
|
}
|
|
V1 = Z1_1 + pos*(Z1_2-Z1_1);
|
|
|
|
if(FT2==null){
|
|
Z2_1=0;
|
|
Z2_2=0;
|
|
}
|
|
else{
|
|
Z2_1 = FT2.Zfkt(BS.getEP1());
|
|
Z2_2 = FT2.Zfkt(BS.getEP2());
|
|
}
|
|
V2 = Z2_1 + pos*(Z2_2-Z2_1);
|
|
return Math.max(V1,V2);
|
|
}
|
|
|
|
|
|
/** computes the topological relationship between this and R2 */
|
|
public FuzzyTopRel topolRelation(FRegion R2){
|
|
|
|
FuzzyTopRel result = new FuzzyTopRel();
|
|
|
|
fTriangle Current;
|
|
BasicTriangle CurrentBasic;
|
|
BasicPoint[] Corners;
|
|
BasicSegment[] Sides;
|
|
fTriangle FT2;
|
|
|
|
for(int i=0;i<fTs.getSize();i++){
|
|
Current = (fTriangle) fTs.get(i);
|
|
CurrentBasic = (BasicTriangle) Current.basic();
|
|
Corners = CurrentBasic.getBasicPoints();
|
|
Sides = CurrentBasic.getSides();
|
|
double Z1_1,Z1_2,Z1_3;
|
|
double Z2_1,Z2_2,Z2_3;
|
|
double M1,M2;
|
|
double VM1_1,VM1_2,VM2_1,VM2_2;
|
|
double[] values1;
|
|
double[] values2;
|
|
|
|
// first process CornerPoints
|
|
for(int cp=0;cp<Corners.length;cp++){
|
|
if(R2.contains(Corners[cp])){
|
|
Z1_1 = maxZfkt(Corners[cp]);
|
|
Z2_1 = R2.maxZfkt(Corners[cp]);
|
|
result.computeValue(Z1_1,Z2_1);
|
|
}
|
|
} // process cornerpoints
|
|
|
|
// second process Sides
|
|
for(int s=0;s<Sides.length;s++){
|
|
if(R2.contains(Sides[s])){
|
|
values1 = getValues(Sides[s]);
|
|
values2 = R2.getValues(Sides[s]);
|
|
Z1_1 = values1[0];
|
|
Z1_2 = values1[1];
|
|
Z2_1 = values2[0];
|
|
Z2_2 = values2[1];
|
|
if(Z1_1!=Z2_1)
|
|
result.computeValue(Z1_1,Z2_1);
|
|
if(Z1_2!=Z2_2)
|
|
result.computeValue(Z1_1,Z2_1);
|
|
|
|
if( (values1.length==2) & (values2.length==2)) {
|
|
if( (Z1_1==Z2_1) & (Z1_2==Z2_2)) // equals segments
|
|
result.computeValue(0.5,0.5);
|
|
if( (Z1_1-Z2_1)*(Z1_2-Z2_2)<0) // crossing segments
|
|
result.computeValue(0.5,0.5);
|
|
} // in both region are nor crossing segments
|
|
else if( values1.length==2){
|
|
M2 = values2[2];
|
|
VM2_2 = values2[3];
|
|
VM1_2 = getMaxValue(Sides[s],M2);
|
|
result.computeValue(VM1_2,VM2_2);
|
|
// explore crossing segment parts
|
|
if( (Z1_1-Z2_1)*(VM1_2-VM2_2) <0)
|
|
result.computeValue(0.5,0.5);
|
|
if( (VM1_2-VM2_2)*(Z1_2-Z2_2) <0)
|
|
result.computeValue(0.5,0.5);
|
|
}
|
|
else if( values2.length==2){
|
|
M1 = values1[2];
|
|
VM1_1 = values1[3];
|
|
VM2_1 = R2.getMaxValue(Sides[s],M1);
|
|
result.computeValue(VM1_1,VM2_1);
|
|
// crossing segments
|
|
if( (Z1_1-Z2_1)*(VM1_1-VM2_1)<0)
|
|
result.computeValue(0.5,0.5);
|
|
if( (VM1_1-VM2_1)*(Z1_2-Z2_2)<0)
|
|
result.computeValue(0.5,0.5);
|
|
}
|
|
else { // both region having crossing segments
|
|
|
|
if(values1[2]<=values2[2]) {
|
|
M1 = values1[2];
|
|
M2 = values2[2];
|
|
VM1_1 = values1[3];
|
|
VM1_2 = getMaxValue(Sides[s],M2);
|
|
VM2_1 = R2.getMaxValue(Sides[s],M1);
|
|
VM2_2 = values2[3];
|
|
}
|
|
else {
|
|
M1 = values2[2];
|
|
M2 = values1[2];
|
|
VM1_1 = getMaxValue(Sides[s],M1);
|
|
VM1_2 = values1[3];
|
|
VM2_1 = values2[3];
|
|
VM2_2 = R2.getMaxValue(Sides[s],M2);
|
|
}
|
|
result.computeValue(VM1_1,VM2_1);
|
|
result.computeValue(VM1_2,VM2_2);
|
|
|
|
// explore crosses
|
|
if( (Z1_1-Z2_1)*(VM1_1-VM2_1) <0)
|
|
result.computeValue(0.5,0.5);
|
|
if( (M1!=M2) && ( (VM1_1-VM2_1)*(VM1_2-VM2_2)<0) )
|
|
result.computeValue(0.5,0.5);
|
|
if( (VM1_2-VM2_2)*(Z1_2-Z2_2)<0)
|
|
result.computeValue(0.5,0.5);
|
|
|
|
} // else (both region have crossing segments)
|
|
} // if contains segment
|
|
} // process sides
|
|
|
|
// process inner triangles
|
|
FT2 = (fTriangle) R2.fTs.search(CurrentBasic);
|
|
if(FT2!=null){
|
|
Z1_1 = Current.getZ1();
|
|
Z1_2 = Current.getZ2();
|
|
Z1_3 = Current.getZ3();
|
|
Z2_1 = FT2.getZ1();
|
|
Z2_2 = FT2.getZ2();
|
|
Z2_3 = FT2.getZ3();
|
|
|
|
if( (Z1_1<Z2_1 & Z1_2<Z2_2 & Z1_3<Z2_3) | // all under or
|
|
(Z1_1>Z2_1 & Z1_2>Z2_2 & Z1_3>Z2_3) ) // all over
|
|
result.computeValue(Z1_1,Z2_1);
|
|
else
|
|
if(Z1_1==Z2_1 & Z1_2==Z2_2 & Z1_3==Z2_3)
|
|
result.computeValue(0.5,0.5);
|
|
else { // the triangles are crossing;
|
|
// this covers all cases
|
|
result.computeValue(0.3,0.7);
|
|
result.computeValue(0.7,0.3);
|
|
result.computeValue(0.5,0.5);
|
|
}
|
|
}
|
|
|
|
} // for all containing TRiangles
|
|
|
|
return result;
|
|
|
|
} // topolRelation
|
|
|
|
|
|
|
|
/** compute the topological relationship between this and CO */
|
|
public FuzzyTopRel topolRelation(CompositeObject CO){
|
|
FuzzyTopRel result;
|
|
if(CO instanceof FPoint){
|
|
result = ((FPoint)CO).topolRelation(this);
|
|
result.makeSym();
|
|
return result;
|
|
}
|
|
if(CO instanceof FLine){
|
|
result = ((FLine)CO).topolRelation(this);
|
|
result.makeSym();
|
|
return result;
|
|
}
|
|
if(CO instanceof FRegion){
|
|
return topolRelation((FRegion) CO);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
|
|
|
|
/** returns the ListExpr representation of this FRegion
|
|
* (SF , (<TriangleList>))
|
|
*/
|
|
public ListExpr toListExpr(){
|
|
// first create the SegmentList
|
|
ListExpr Triangles;
|
|
ListExpr Last=null;
|
|
if(fTs.getSize()==0)
|
|
Triangles = ListExpr.theEmptyList();
|
|
else {
|
|
Triangles = ListExpr.oneElemList(
|
|
((fTriangle)fTs.get(0)).toListExpr());
|
|
Last = Triangles;
|
|
}
|
|
fTriangle NextTriangle;
|
|
for(int i=1;i<fTs.getSize();i++){
|
|
NextTriangle = (fTriangle) fTs.get(i);
|
|
Last=ListExpr.append(Last,NextTriangle.toListExpr());
|
|
}
|
|
return ListExpr.twoElemList(
|
|
ListExpr.realAtom((float)SF),Triangles);
|
|
}
|
|
|
|
/** creates a new ListEXpr <type,value>*/
|
|
public ListExpr toTypedListExpr(){
|
|
return ListExpr.twoElemList(
|
|
ListExpr.symbolAtom("fregion"),toListExpr());
|
|
}
|
|
|
|
|
|
/** read this FRegion from a ListExpr
|
|
* @return true if LE is a valid Representaion of a FRegion
|
|
* all valid Triangles of this List are inserted
|
|
*/
|
|
public boolean readFromListExpr(ListExpr LE){
|
|
SF = 1.0;
|
|
fTs.makeEmpty();
|
|
computeBoundingBox();
|
|
if(LE==null)
|
|
return false;
|
|
if(LE.listLength()!=2)
|
|
return false;
|
|
ListExpr SFList = LE.first();
|
|
if( !( SFList.isAtom() &&
|
|
(SFList.atomType()==ListExpr.INT_ATOM ||
|
|
SFList.atomType()==ListExpr.REAL_ATOM)))
|
|
return false;
|
|
double z= SFList.atomType()==ListExpr.INT_ATOM ?
|
|
SFList.intValue() :
|
|
SFList.realValue();
|
|
if(z<=0)
|
|
return false;
|
|
this.SF = z;
|
|
|
|
|
|
ListExpr Triangles = LE.second();
|
|
fTriangle T;
|
|
boolean ok = true;
|
|
while( !Triangles.isEmpty() & ok) {
|
|
T = new fTriangle(0,0,0,0,0,0,0,0,0);
|
|
if(T.readFromListExpr(Triangles.first())){
|
|
add(T);
|
|
Triangles=Triangles.rest();
|
|
}
|
|
else
|
|
ok = false;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
/** returns a String representation of
|
|
* the corresponding ListExpr
|
|
*/
|
|
public String toListString(){
|
|
return toListExpr().writeListExprToString();
|
|
}
|
|
|
|
|
|
/** read the FRegion from a String representation of a ListExpr
|
|
* @return true if List is a String of a ListExpr containing
|
|
* a correct FRegion
|
|
*/
|
|
public boolean readFromListString(String List){
|
|
ListExpr LE = new ListExpr();
|
|
if(LE.readFromString(List)!=0){
|
|
return false;
|
|
}
|
|
else{
|
|
return readFromListExpr(LE);
|
|
}
|
|
}
|
|
|
|
/** this method is used for reading a fuzzy region
|
|
* from a byte array;
|
|
* returns null if the construction of the object failed
|
|
*/
|
|
public static FRegion readFrom(byte[] buffer){
|
|
try{
|
|
ObjectInputStream ois;
|
|
ois = new ObjectInputStream(new
|
|
ByteArrayInputStream(buffer));
|
|
FRegion res = (FRegion) ois.readObject();
|
|
ois.close();
|
|
return res;
|
|
} catch(Exception e){
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
/** this method serialized an object */
|
|
public byte[] writeToByteArray(){
|
|
|
|
try{
|
|
ByteArrayOutputStream byteout;
|
|
byteout = new ByteArrayOutputStream(fTs.getSize()*16+25);
|
|
ObjectOutputStream objectout;
|
|
objectout = new ObjectOutputStream(byteout);
|
|
objectout.writeObject(this);
|
|
objectout.flush();
|
|
byte[] res = byteout.toByteArray();
|
|
objectout.close();
|
|
return res;
|
|
} catch(Exception e){
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/** computes a hash-value for this FPoint */
|
|
public int getHashValue(){
|
|
return Math.abs((BB.getMaxX()-BB.getMinX())*
|
|
(BB.getMaxY()-BB.getMinY())+BB.getMinX()
|
|
+BB.getMinY());
|
|
}
|
|
|
|
|
|
// define constants for the operators
|
|
private static final int UNION = 0;
|
|
private static final int INTERSECTION=1;
|
|
private static final int ADD=2;
|
|
private static final int SUBTRACT=3;
|
|
|
|
private static final int SCALEDUNION=4;
|
|
private static final int SCALEDINTERSECTION=5;
|
|
private static final int SCALEDADD=6;
|
|
private static final int SCALEDDIFFERENCE=7;
|
|
|
|
} // FRegion;
|
|
|