Files
secondo/Algebras/Fuzzy/fuzzyobjects/composite/FPoint.java

1572 lines
39 KiB
Java
Raw Normal View History

2026-01-23 17:03:45 +08:00
//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 spatial points
* @author Thomas Behr
*/
public class FPoint implements CompositeObject{
/** the factor of scale */
protected double SF;
/**
* the set of fuzzy elementary objects
* this set must be ordered
*/
protected SortedObjects feP; // the fuzzy elementary points
/** the Bounding box of this FPoint */
protected BoundingBox BB = new BoundingBox();
/** set a new factor of scale
* @param SF the new factor, must be greater then 0
* @result true if sucessfull
*/
public boolean setSF(double SF){
if (SF>0){
this.SF = SF;
return true;
}
else return false;
}
/* returns the number of containing fuzzy elementary points */
public int getSize(){
return feP.getSize();
}
public fEPoint getPointAt(int index){
if(index<0 || index >=feP.getSize())
return null;
else
return (fEPoint) feP.get(index);
}
/**
* creates a new FPoint
* whith given factor of scale
*/
public FPoint(double scale){
feP = new SortedObjects();
SF = scale;
no++;
}
/**
* creates a new FPoint
* with a factor of scale of 1.0
*/
public FPoint() {
this(1.0);
}
/**
* returns the current factor of scale
*/
public double getSF(){ return SF;}
/** returns the bounding box of this point */
public BoundingBox getBoundingBox(){ return BB; }
/**
* returns the dimension of a point,
* i.e. 0
*/
public int getDim() { return 0; }
/**
* check whether this is a valid point
* i.e. here is ckecked whether all containing fuzzy
* elementary points
* are valid and the factor of scale is greater then 0
*/
public boolean isValid(){
return SF>0 & feP.allValid();
}
/**
* returns a readable representation of this fPoint
*/
public String toString(){
return "FPoint (SF="+SF+")\n"+feP.toString();
}
/** prints out a representation of this FPoint to
* the standard-oiutput
* it's for debuggng only
*/
public void print(){
System.out.println(this);
}
/** computes the bounding boxc of this point */
private void computeBoundingBox(){
if(feP.isEmpty())
BB.setBox(0,0,0,0);
else{
fEPoint FP = (fEPoint) feP.get(0);
int minX = FP.getMinX();
int minY = FP.getMinY();
int maxX = FP.getMaxX();
int maxY = FP.getMaxY();
int cX,cY;
for (int i=1;i<feP.getSize();i++){
FP = (fEPoint) feP.get(i);
cX = FP.getMinX();
cY = FP.getMinY();
if(cX < minX)
minX = cX;
if(cY < minY)
minY = cY;
cX = FP.getMaxX();
cY = FP.getMaxY();
if(cX > maxX)
maxX = cX;
if(cY > maxY)
maxY = cY;
}
BB.setBox(minX,minY,maxX,maxY);
}
}
/**
* inserted a new fuzzy elementary point to this FPoint
* @param SP the fEPoint to inserted
* @return
* <ul>
* <li> true if SP is not containing in original FPoint
* <li> false if SP is in FPoint, SP is not inserted
* </ul>
*/
public boolean add(fEPoint SP){
boolean first = feP.isEmpty();
boolean ok = feP.insert(SP.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>SP.getMinX())
minX = SP.getMinX();
if(minY>SP.getMinY())
minY = SP.getMinY();
if(maxX<SP.getMaxX())
maxX = SP.getMaxX();
if(maxY<SP.getMaxY())
maxY = SP.getMaxY();
BB.setBox(minX,minY,maxX,maxY);
}
else
BB.setBox(SP.getMinX(),SP.getMinY(),
SP.getMaxX(),SP.getMaxY());
}
return ok;
}
/**
* updated a fEPoint containing in this FPoint
* @param SP the fEPoint to updated
* @return
* <ul>
* <li> true if SP is containing in this
* <li> false SP is not a element of this, nothing to update
* </ul>
*/
public boolean update(fEPoint SP){
if(feP.update(SP.copy())){
int minX = BB.getMinX();
int minY = BB.getMinY();
int maxX = BB.getMaxX();
int maxY = BB.getMaxY();
if(minX>SP.getMinX())
minX = SP.getMinX();
if(minY>SP.getMinY())
minY = SP.getMinY();
if(maxX<SP.getMaxX())
maxX = SP.getMaxX();
if(maxY<SP.getMaxY())
maxY = SP.getMaxY();
BB.setBox(minX,minY,maxX,maxY);
return true;
}
return false;
}
/**
* updated a containing fEPoint
* if SP is not containing in this, SP is added to this
* @param SP the fEPoint to updated/added
*/
public void overwrite(fEPoint SP){
boolean first = feP.isEmpty();
if (!feP.update(SP))
feP.insert(SP);
if(!first){
int minX = BB.getMinX();
int minY = BB.getMinY();
int maxX = BB.getMaxX();
int maxY = BB.getMaxY();
if(minX>SP.getMinX())
minX = SP.getMinX();
if(minY>SP.getMinY())
minY = SP.getMinY();
if(maxX<SP.getMaxX())
maxX = SP.getMaxX();
if(maxY<SP.getMaxY())
maxY = SP.getMaxY();
BB.setBox(minX,minY,maxX,maxY);
}
else
BB.setBox(SP.getMinX(),SP.getMinY(),
SP.getMaxX(),SP.getMaxY());
}
/**
* creates a new FPoint and invokes
* <a href="#overwrite(fEPoint)"> * overwrite(fEPoint) </a>
* @return true if (x,y,Z) is a valid fEPoint
*/
public boolean overwrite(int x, int y , double Z){
fEPoint P = new fEPoint(x,y,Z);
boolean result = P.isValid();
if (result)
overwrite(P);
return result;
}
/**
* deletes a fEPoint with Basic BP from this
* @return true if this contains BP
*/
public boolean delete(BasicPoint BP){
boolean result = feP.delete(BP);
if(result & (
BP.getMinX()==BB.getMinX() |
BP.getMaxX()==BB.getMaxX() |
BP.getMinY()==BB.getMinY() |
BP.getMaxY()==BB.getMaxY() ) )
computeBoundingBox();
return result;
}
/**
* computes all membershipvalues of this on (x,y)
*/
public double[] ZRel(double x, double y) {
double[] Rel = new double[1];
Rel[0] = 0.0;
if ( (int)x == x && (int)y==y){ // x and y are integers
fEPoint P = (fEPoint) feP.search(
new BasicPoint((int)x,(int)y) );
if (P!=null)
Rel[0] = P.getZ();
}
return Rel;
} // ZRel
/**
* computes the minimal membershipvalue on (x,y)
*/
public double minZfkt(double x, double y){
double[] Rel = ZRel(x,y);
double min = Rel[0];
for(int i=1;i<Rel.length;i++)
if(min>Rel[i])
min =Rel[i];
return min;
}
/**
* computes the maximal membership-value on (x,y)
*/
public double maxZfkt(double x, double y){
double[] Rel = ZRel(x,y);
double max = Rel[0];
for(int i=1;i<Rel.length;i++)
if(max<Rel[i])
max =Rel[i];
return max;
}
/**
* computes the middle membership-value on (x,y)
*/
public double midZfkt(double x, double y){
double[] Rel = ZRel(x,y);
double sum =0;
for(int i=0;i<Rel.length;i++)
sum += Rel[i];
return sum / Rel.length;
}
/**
* computes the minimal membership-value on BP
*/
public double minZfkt(BasicPoint BP){
double[] Rel = ZRel(BP);
double min = Rel[0];
for(int i=1;i<Rel.length;i++)
if(min>Rel[i])
min =Rel[i];
return min;
}
/** computes the maximal membership-value on BP */
public double maxZfkt(BasicPoint BP){
double[] Rel = ZRel(BP);
double max = Rel[0];
for(int i=1;i<Rel.length;i++)
if(max<Rel[i])
max =Rel[i];
return max;
}
/** computes the middle membership-value on BP */
public double midZfkt(BasicPoint BP){
double[] Rel = ZRel(BP);
double sum =0;
for(int i=0;i<Rel.length;i++)
sum += Rel[i];
return sum/Rel.length;
}
/** computes all membership-values on BP */
public double[] ZRel(BasicPoint BP){
double[] result = new double[1];
result[0]=0;
fEPoint P = (fEPoint) feP.search(BP);
if(P!=null)
result[0] = P.getZ();
return result;
}
/**
* computes the memebrship-value on (x,y) with basic BP
*/
public double Zfkt(double x, double y, BasicPoint BP){
double result=0.0;
if ( (int)x == x && (int) y ==y)
if (BP.getX()==x && BP.getY()==y) {
fEPoint P = (fEPoint) feP.search(BP);
if (P!=null)
result = P.getZ();
}
return result;
}
/**
* computes the memebrship-value on BP1 with basic BP2
*/
public double Zfkt( BasicPoint BP1, BasicPoint BP2){
double result=0.0;
if( BP1.equals(BP2) ) {
Object O = feP.search(BP1);
if (O!=null){
fEPoint P = (fEPoint) O;
result = P.getZ();
}
}
return result;
}
/**
* computes all BasicPoints containing in this
*/
public BasicPoint[] basics() {
BasicPoint[] result = new BasicPoint[feP.getSize()];
if(feP.isEmpty())
return result;
else{
for(int i=0;i<feP.getSize();i++)
result[i] = (BasicPoint) ((fEPoint)feP.get(i)).basic();
}
return result;
} // basics
/**
* computes the maximal membership-value containing in this
*/
public double maxZ(){
double max = 0.0;
for(int i=0;i<feP.getSize();i++)
if (max < ((fEPoint)feP.get(i)).getZ())
max = ((fEPoint)feP.get(i)).getZ();
return max;
} // maxZ
/**
* computes the minimal membership-value containing in this
*/
public double minZ(){
if (feP.isEmpty())
return 0;
else {
double min =1;
for(int i=0;i<feP.getSize();i++)
if (min> ((fEPoint)feP.get(i)).getZ())
min = ((fEPoint)feP.get(i)).getZ();
return min;
}
} // minZ
/**
* returns a copy of this
*/
public FPoint copy(){
FPoint C = new FPoint(SF);
C.feP = feP.copy();
C.BB = BB.copy();
return C;
}
/**
* check whether this is containing elements
*/
public boolean isEmpty(){
return feP.isEmpty();
}
/**
* set the set of fEPoints from P1 equal to the set of P2
*/
protected static void setfeP(FPoint P1, FPoint P2){
P1.feP = P2.feP;
P1.BB = P2.BB;
}
/*************************************************************
Operators
*************************************************************/
/** computes the union from this with With */
public FPoint union(FPoint With){
return operator(With,UNION);
}
/** computes the scaled_union from this with With */
public FPoint scaledUnion(FPoint With){
FPoint result = operator(With,SCALEDUNION);
result.norm();
return result;
}
/** computes the intersection from this with With */
public FPoint intersection(FPoint With){
return operator(With,INTERSECTION);
}
/** computes the scaled_intersection from this with With */
public FPoint scaledIntersection(FPoint With){
FPoint result = operator(With,SCALEDINTERSECTION);
result.norm();
return result;
}
/** computes the operator add from this with With */
public FPoint add(FPoint With){
return operator(With,ADD);
}
/** computes the operator scaled_add from this with With */
public FPoint scaledAdd(FPoint With){
FPoint result = operator(With,SCALEDADD);
result.norm();
return result;
}
/** computes the difference from this with With */
public FPoint difference(FPoint With){
return operator(With,SUBTRACT);
}
/** computes the scaled_difference from this with With */
public FPoint scaledDifference(FPoint With){
FPoint result = operator(With,SCALEDDIFFERENCE);
result.norm();
return result;
}
/** computes the alpha-cut of this */
public FPoint alphaCut(double alpha, boolean strong){
FPoint result = new FPoint(SF);
fEPoint Current;
boolean isValid;
double Z;
for(int i=0; i<feP.getSize(); i++){
Current = (fEPoint) feP.get(i);
Z = Current.getZ();
if (strong)
isValid = Z>alpha;
else
isValid = Z>= alpha;
if(isValid)
result.feP.insert(Current.copy());
}
result.computeBoundingBox();
return result;
}
/** computes the number of elements in this */
public double basicCard(){
return feP.getSize();
}
/** computes the weighted number of elements in this */
public double card(){
double result = 0;
for(int i=0;i<feP.getSize();i++)
result += ((fEPoint) feP.get(i)).getZ();
return result;
}
/**
* computes the similarity in the basic from this whith P2
*/
public double basicSimilar(FPoint P2){
FPoint Funion = this.union(P2);
FPoint Fintersection = this.intersection(P2);
if (Funion.isEmpty())
return 1.0;
else
return Fintersection.basicCard() / Funion.basicCard();
}
/**
* computes the similarity of this with P2
*/
public double similar(FPoint P2){
FPoint Funion = this.union(P2);
FPoint Fintersection = this.intersection(P2);
if (Funion.isEmpty())
return 1.0;
else
return Fintersection.card() / Funion.card();
}
/**
* make this sharp
* i.e. set all membershipvalues on 1.0
*/
public FPoint sharp(){
FPoint result = new FPoint(1);
fEPoint Current;
for(int i=0;i<feP.getSize();i++){
Current = new fEPoint((BasicPoint) (feP.get(i)).basic(),1);
result.add(Current);
}
return result;
}
/**
* computes the operator mid
*/
public static FPoint mid(FPoint[] Pts){
if(Pts.length==0) return null;
FPoint result = new FPoint(1);
int[] current = new int[Pts.length];
int[] max = new int[Pts.length];
boolean[] ready = new boolean[Pts.length];
boolean allready = true;
// initialize the variables
for(int i=0;i<Pts.length;i++){
current[i]=0;
max[i]= Pts[i].feP.getSize();
ready[i] = current[i]<max[i];
if(!ready[i]) allready=false;
}
Vector allSmallest = new Vector(); // the smallest coordinate
Vector Numbers = new Vector(); // the positions in Pts
while(!allready){
allready=true;
allSmallest = new Vector();
Numbers = new Vector();
// search all smallest Triangles
fEPoint currentP;
BasicPoint compareP;
for(int i=0;i<Pts.length;i++){
if(current[i]<max[i]) {
allready=false;
currentP = (fEPoint) Pts[i].feP.get(current[i]);
if(allSmallest.size()==0) {
allSmallest.add(currentP);
Numbers.add(new Integer(i));
}
else {
compareP = (BasicPoint)((fEPoint)
allSmallest.get(0)).basic();
int comp = currentP.basic().compareTo(compareP);
if(comp==0) { // a Triangle with smallest Basic
allSmallest.add(currentP);
Numbers.add(new Integer(i));
}
if(comp<0) { // new smallest Triangle
allSmallest = new Vector();
Numbers = new Vector();
allSmallest.add(currentP);
Numbers.add(new Integer(i));
}
// in the case comp>0 is nothing to do
} // not the first coordinate
} // current Point contains unprocessing coordinates
} // for all Pts
// all smallest Points are in Vector allSmallest and
// the positions of this one are in Numbers
if(!allready){
double Z=0;
BasicPoint BP = (BasicPoint) ((fEPoint)
allSmallest.get(0)).basic();
fEPoint CP;
for(int i=0;i<allSmallest.size();i++){
// update numbers
int c = ((Integer)Numbers.get(i)).intValue();
current[c]++;
CP = (fEPoint) allSmallest.get(i);
Z += CP.getZ();
}
Z = Z / Pts.length;
result.feP.insert( new fEPoint(BP,Z));
}
} // while not all ready
result.computeBoundingBox();
return result;
}
/**
* computes the operator scaled_mid
*/
public static FPoint scaledMid(FPoint[] Pts){
if(Pts.length==0) return null;
FPoint result = new FPoint(1);
int[] current = new int[Pts.length];
int[] max = new int[Pts.length];
boolean[] ready = new boolean[Pts.length];
boolean allready = true;
// initialize the variables
for(int i=0;i<Pts.length;i++){
current[i]=0;
max[i]= Pts[i].feP.getSize();
ready[i] = current[i]<max[i];
if(!ready[i]) allready=false;
}
Vector allSmallest = new Vector(); // the smallest coordinate
Vector Numbers = new Vector(); // the positions in Pts
while(!allready){
allready=true;
allSmallest = new Vector();
Numbers = new Vector();
// search all smallest Triangles
fEPoint currentP;
BasicPoint compareP;
for(int i=0;i<Pts.length;i++){
if(current[i]<max[i]) {
allready=false;
currentP = (fEPoint) Pts[i].feP.get(current[i]);
if(allSmallest.size()==0) {
allSmallest.add(currentP);
Numbers.add(new Integer(i));
}
else {
compareP = (BasicPoint) ((fEPoint)
allSmallest.get(0)).basic();
int comp = currentP.basic().compareTo(compareP);
if(comp==0) { // a Triangle with smallest Basic
allSmallest.add(currentP);
Numbers.add(new Integer(i));
}
if(comp<0) { // new smallest Triangle
allSmallest = new Vector();
Numbers = new Vector();
allSmallest.add(currentP);
Numbers.add(new Integer(i));
}
// in the case comp>0 is nothing to do
} // not the first coordinate
} // current Point contains unprocessing coordinates
} // for all Pts
// all smallest Points are in Vector allSmallest and
// the positions of this one are in Numbers
if(!allready){
double Z=0;
BasicPoint BP = (BasicPoint) ((fEPoint)
allSmallest.get(0)).basic();
fEPoint CP;
for(int i=0;i<allSmallest.size();i++){
// update numbers
int c = ((Integer)Numbers.get(i)).intValue();
current[c]++;
CP = (fEPoint) allSmallest.get(i);
Z += CP.getZ()*Pts[c].SF;
}
Z = Z / Pts.length;
result.feP.insert( new fEPoint(BP,Z));
}
} // while not all ready
result.norm();
result.computeBoundingBox();
return result;
}
/**
* process elements of two FEPoints
* F1 and F2 must have the same basic
* or can be null
* @param F? the element of FPoint P?
* @param scale? the factor of scale from FPoint P?
* @param goal here is saving the result of this method
* @param Operator the applying operator
*/
private void processElements(fEPoint F1, double scale1,
fEPoint F2, double scale2,
FPoint 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 Z;
fEPoint newFEP;
switch (Operator){
case UNION : { // the union of 2 Points ignoring SFs
if(F1==null)
Goal.feP.insert(F2.copy());
else if(F2==null)
Goal.feP.insert(F1.copy());
else { // both fEPoints are not null
Z = Math.max(F1.getZ(),F2.getZ());
newFEP = new fEPoint((BasicPoint)F1.basic(),Z);
Goal.feP.insert(newFEP);
} // else
}
break;
case INTERSECTION :{
if (F1==null | F2==null)
;
else { // both are not null
Z = Math.min(F1.getZ(),F2.getZ());
newFEP = new fEPoint((BasicPoint)F1.basic(),Z);
Goal.feP.insert(newFEP);
}
} break;
case ADD : {
if(F1==null)
Goal.feP.insert(F2.copy());
else if(F2==null)
Goal.feP.insert(F1.copy());
else { // both fEPoints are not null
Z = Math.min(1,F1.getZ()+F2.getZ());
newFEP = new fEPoint((BasicPoint)F1.basic(),Z);
Goal.feP.insert(newFEP);
} // else
}
break;
case SUBTRACT :{
if(F1 == null)
;
else if(F2==null)
Goal.feP.insert(F1.copy());
else { // both not null
Z = Math.max(0,F1.getZ()-F2.getZ());
if (Z>0) {
newFEP=new fEPoint((BasicPoint)F1.basic(),Z);
Goal.feP.insert(newFEP);
}
}
} break;
case SCALEDUNION :
{ fEPoint newfePoint;
if (F1==null)
newfePoint = new fEPoint((BasicPoint)F2.basic(),
F2.getZ()*scale2);
else if (F2==null)
newfePoint=new fEPoint((BasicPoint)F1.basic(),
F1.getZ()*scale1);
else {
Z = Math.max(F1.getZ()*scale1,F2.getZ()*scale2);
newfePoint = new fEPoint((BasicPoint)F1.basic(),
Z);
} // else
Goal.add(newfePoint);
} break; // scaled union
case SCALEDINTERSECTION :
if (F1==null || F2==null)
;
else {
Z = Math.min(F1.getZ()*scale1,
F2.getZ()*scale2);
Goal.add(new fEPoint( (BasicPoint)
F1.basic(),Z));
} break;
case SCALEDADD : {
if(F1==null)
Goal.add(new fEPoint( (BasicPoint)F2.basic(),
F2.getZ()*scale2));
else if(F2==null)
Goal.add(new fEPoint( (BasicPoint)F1.basic(),
F1.getZ()*scale1 ));
else {
Goal.add(new fEPoint((BasicPoint)F1.basic(),
F1.getZ()*scale1 +
F2.getZ()*scale2 ));
}
} break;
case SCALEDDIFFERENCE : {
if(F1==null)
Goal.add(new fEPoint( (BasicPoint) F2.basic(),
-F2.getZ()*scale2 ));
else if(F2==null)
Goal.add(new fEPoint( (BasicPoint) F1.basic(),
F1.getZ()*scale1 ));
else {
Goal.add(new fEPoint( (BasicPoint) F1.basic(),
F1.getZ()*scale1 -
F2.getZ()*scale2 ));
}
} break;
default : System.out.println("operator not implemented");
} // switch
} // processElements
/**
* the 'template' for many operators
* @param FP the second operand
* @param op the operator
*/
protected FPoint operator(FPoint FP, int op){
// a kind of mergesort
int my = 0;
int fromFP = 0; // already processed
int maxMy = feP.getSize(); // numbers of elements
int maxFromFP = FP.feP.getSize();
FPoint result = new FPoint(1);
fEPoint myFirst=null; // the first unprocessed elements
fEPoint FPFirst=null;
if(maxMy>0) // needed if a empty point is involve
myFirst= (fEPoint) feP.get(0);
if(maxFromFP>0)
FPFirst = (fEPoint) FP.feP.get(0);
if (maxMy >0 && maxFromFP>0){
myFirst = (fEPoint) feP.get(my);
FPFirst = (fEPoint) FP.feP.get(fromFP);
int compareResult;
while(my<maxMy && fromFP<maxFromFP){
// both sets have unprocessed elements
compareResult=myFirst.basic().compareTo(FPFirst.basic());
if(compareResult < 0) {
processElements(myFirst,SF,null,FP.SF,result,op);
my++;
if (my<maxMy)
myFirst = (fEPoint) feP.get(my);
}
else if(compareResult > 0){
processElements(null,SF,FPFirst,FP.SF,result,op);
fromFP++;
if(fromFP<maxFromFP)
FPFirst = (fEPoint) FP.feP.get(fromFP);
} else { // elements have the same basic
processElements(myFirst,SF,FPFirst,FP.SF,result,op);
my++;
fromFP++;
if (my<maxMy)
myFirst = (fEPoint) feP.get(my);
if (fromFP<maxFromFP)
FPFirst = (fEPoint) FP.feP.get(fromFP);
}
} // while
} // if
// elements from one (or both) regions are processed
while(my < maxMy){ // this have still elements
processElements(myFirst,SF,null,FP.SF,result,op);
my++;
if (my<maxMy)
myFirst = (fEPoint) feP.get(my);
}
while (fromFP < maxFromFP){ // FP have still elements
processElements(null,SF,FPFirst,FP.SF,result,op);
fromFP++;
if(fromFP<maxFromFP)
FPFirst = (fEPoint) FP.feP.get(fromFP);
}
result.computeBoundingBox();
return result;
}
/**
* normalize this
*/
private void norm(){
if (isEmpty()) return; // nothing to do
// first compute Zmin and Zmax
double Zmin = 0;
double Zmax = 0;
fEPoint Current;
for (int i=0; i< feP.getSize();i++){
Current = (fEPoint) feP.get(i);
if(Current.getZ()>Zmax)
Zmax = Current.getZ();
if(Current.getZ()<Zmin)
Zmin = Current.getZ();
}
if(Zmin > 0) Zmin=0;
if(Zmax==0 & Zmin==0)
feP.makeEmpty();
else{
double SFnew = Zmax - Zmin;
SortedObjects newfePs= new SortedObjects();
double Z;
fEPoint fePnew;
for(int i=0;i<feP.getSize();i++){
Current = (fEPoint) feP.get(i);
Z = Current.getZ();
fePnew = new fEPoint((BasicPoint) Current.basic(),
(Z-Zmin)/SFnew);
if (fePnew.getZ() >0)
newfePs.insert(fePnew);
} // for
SF = SFnew*SF;
feP = newfePs;
}
computeBoundingBox();
}
/*************************************************************
* *
* topological relationships *
* *
*************************************************************/
/************************************************************
* *
* Topology in the basic *
* *
*************************************************************/
/**
* returns a String representing the topological relationship
* between this and P2
* if fuzzy is false the membershipvalues are not evaluated
*/
public String basicTopolRelationString(FPoint P2){
M9Int matrix = basicTopolRelation(P2);
String result;
if (matrix ==null)
result="undefined";
else{
result = matrix.toString();
}
return result;
}
// relations between 2 points
/**
* compute the topological relations of the basic between
* this and P2
*/
M9Int basicTopolRelation(FPoint P2){
if(this.isEmpty() | P2.isEmpty()) return null;
M9Int result = new M9Int();
// the standard-entries for 2 points
result.setValue(false,M9Int.BOUNDARY,M9Int.INTERIOR);
result.setValue(false,M9Int.BOUNDARY,M9Int.BOUNDARY);
result.setValue(false,M9Int.BOUNDARY,M9Int.EXTERIOR);
result.setValue(false,M9Int.INTERIOR,M9Int.BOUNDARY);
result.setValue(false,M9Int.EXTERIOR,M9Int.BOUNDARY);
result.setValue(true,M9Int.EXTERIOR,M9Int.EXTERIOR);
// compute the next intersections
// merge sort like
int currentThis=0;
int currentP2=0;
int maxThis = feP.getSize();
int maxP2 = P2.feP.getSize();
fEPoint FirstThis = (fEPoint)feP.get(0);
fEPoint FirstP2 = (fEPoint)P2.feP.get(0);
int compareResult;
boolean ready = false; // all possible intersections are true ?
while(currentThis<maxThis & currentP2<maxP2 & !ready){
compareResult = FirstThis.basic().compareTo(FirstP2.basic());
if(compareResult<0){
// a (basic)Point of this is in exterior of P2
result.setValue(true,M9Int.INTERIOR,M9Int.EXTERIOR);
currentThis++;
if (currentThis<maxThis)
FirstThis = (fEPoint) feP.get(currentThis);
}
if(compareResult>0){
// a (basic)Point of P2 is in the exterior of this
result.setValue(true,M9Int.EXTERIOR,M9Int.INTERIOR);
currentP2++;
if(currentP2<maxP2)
FirstP2 = (fEPoint) P2.feP.get(currentP2);
}
if(compareResult==0){
// this and P2 have a common coordinate
result.setValue(true,M9Int.INTERIOR,M9Int.INTERIOR);
currentThis++;
currentP2++;
if(currentThis<maxThis)
FirstThis=(fEPoint) feP.get(currentThis);
if(currentP2<maxP2)
FirstP2=(fEPoint) P2.feP.get(currentP2);
} // if common basic
ready = result.getValue(M9Int.INTERIOR,M9Int.INTERIOR) &
result.getValue(M9Int.INTERIOR,M9Int.EXTERIOR) &
result.getValue(M9Int.EXTERIOR,M9Int.INTERIOR);
} // while (both Points have components and not ready)
if( !ready & currentThis<maxThis){
// this have coordinates (not in P2)
result.setValue(true,M9Int.INTERIOR,M9Int.EXTERIOR);
}
if(!ready & currentP2<maxP2){
// P2 have coordinates in exterior of this
result.setValue(true,M9Int.EXTERIOR,M9Int.INTERIOR);
}
return result;
}
/**
* computes the topological relationship
* between this and Line in their basic
*/
M9Int basicTopolRelation(FLine Line){
if(this.isEmpty() | Line.isEmpty()) return null;
M9Int result = new M9Int();
// the "standard"-values between Point and line
result.setValue(true,M9Int.EXTERIOR,M9Int.EXTERIOR);
result.setValue(false,M9Int.BOUNDARY,M9Int.INTERIOR);
result.setValue(false,M9Int.BOUNDARY,M9Int.BOUNDARY);
result.setValue(false,M9Int.BOUNDARY,M9Int.EXTERIOR);
result.setValue(true,M9Int.EXTERIOR,M9Int.INTERIOR);
// compute the intersections of interior of this
// with the parts of Line
boolean ready=false;
int number;
fEPoint currentFP;
BasicPoint currentBP;
for(int i=0;i<feP.getSize() & !ready ;i++){
currentFP = (fEPoint) feP.get(i);
currentBP = (BasicPoint) currentFP.basic();
number = Line.numberOfSegments(currentBP);
if(number==0){
result.setValue(true,M9Int.INTERIOR,M9Int.EXTERIOR);
}
if(number==1){
result.setValue(true,M9Int.INTERIOR,M9Int.BOUNDARY);
}
if(number>1){
result.setValue(true,M9Int.INTERIOR,M9Int.INTERIOR);
}
ready = result.getValue(M9Int.INTERIOR,M9Int.INTERIOR) &
result.getValue(M9Int.INTERIOR,M9Int.BOUNDARY) &
result.getValue(M9Int.INTERIOR,M9Int.EXTERIOR);
// all 3 entrys are true, this is no change more possible
}
// intersection exterior of Point / boundary of Line
FPoint LB = Line.boundary();
ready =false;
fEPoint inThis;
for(int i=0;i<LB.feP.getSize()&!ready ;i++){
currentBP = (BasicPoint) LB.feP.get(i).basic();
inThis=(fEPoint)feP.search(currentBP);
if(inThis==null){
result.setValue(true,M9Int.EXTERIOR,M9Int.BOUNDARY);
ready = true;
}
} // for
return result;
}
/**
* computes the topological relationship between the basic
* of this and the basic of a Region
*/
M9Int basicTopolRelation(FRegion Region){
if ( isEmpty() | Region.isEmpty()) return null;
M9Int result = new M9Int();
// this holds ever between Point and Region
result.setValue(false,M9Int.BOUNDARY,M9Int.INTERIOR);
result.setValue(false,M9Int.BOUNDARY,M9Int.BOUNDARY);
result.setValue(false,M9Int.BOUNDARY,M9Int.EXTERIOR);
result.setValue(true,M9Int.EXTERIOR,M9Int.INTERIOR);
result.setValue(true,M9Int.EXTERIOR,M9Int.BOUNDARY);
result.setValue(true,M9Int.EXTERIOR,M9Int.EXTERIOR);
fEPoint currentFP;
BasicPoint currentBP;
double Z1,Z2;
int number;
boolean ready=false;
for(int i=0;i<feP.getSize()&!ready;i++){
currentFP = (fEPoint) feP.get(i);
currentBP = (BasicPoint) currentFP.basic();
number = Region.numberOfTriangles(currentBP);
if(number==0){ // a coordinate in exterior of region
result.setValue(true,M9Int.INTERIOR,M9Int.EXTERIOR);
}
else{ // intersects a true part of region
if(Region.onBoundary(currentBP)) // intersects boundary
result.setValue(true,M9Int.INTERIOR,M9Int.BOUNDARY);
else // in interior of basic of region
result.setValue(true,M9Int.INTERIOR,M9Int.INTERIOR);
} // intersects a true part
ready = result.getValue(M9Int.INTERIOR,M9Int.INTERIOR) &
result.getValue(M9Int.INTERIOR,M9Int.BOUNDARY) &
result.getValue(M9Int.INTERIOR,M9Int.EXTERIOR);
// all possible intersections are true => no more changes
} // for
return result;
}
/**
* returns the topological relationship between this and a
*composite Object(FPoint,FLine or FRegion)
**/
public M9Int basicTopolRelation(CompositeObject CO){
if(CO instanceof FPoint)
return basicTopolRelation( (FPoint) CO);
if(CO instanceof FLine)
return basicTopolRelation( (FLine) CO);
if( CO instanceof FRegion)
return basicTopolRelation((FRegion) CO);
return null;
}
/*********************************************************
* *
* Topology on fuzzy objects *
* *
*********************************************************/
/** computes the fuzzy top. Relation between this and P2 */
public FuzzyTopRel topolRelation(FPoint P2){
FuzzyTopRel result = new FuzzyTopRel();
int maxThis = feP.getSize();
int maxP2 = P2.feP.getSize();
int currentThis = 0;
int currentP2 = 0;
int compare;
BasicPoint BP1,BP2;
fEPoint Q1;
fEPoint Q2;
double Z1,Z2;
while( currentThis<maxThis & currentP2<maxP2){
Q1 =(fEPoint) feP.get(currentThis);
BP1 = (BasicPoint)Q1.basic();
Q2 = (fEPoint)P2.feP.get(currentP2);
BP2 = (BasicPoint)Q2.basic();
compare = BP1.compareTo(BP2);
if(compare <0){
currentThis++;
}
if(compare >0){
currentP2++;
}
if(compare==0){
Z1 = Q1.getZ();
Z2 = Q2.getZ();
// by definition are Z1 and Z2 greater then 0
if(Z1==Z2)
result.setValue(3,true);
if(Z1>Z2)
result.setValue(4,true);
if(Z2>Z1)
result.setValue(5,true);
currentThis++;
currentP2++;
} // compare==0
} // while
return result;
}
/** computes the fuzzy top. Relation between this and L */
public FuzzyTopRel topolRelation(FLine L){
FuzzyTopRel result = new FuzzyTopRel();
int max = feP.getSize();
BasicPoint BP;
fEPoint FP;
double Z1,Z2;
for(int current=0; current<max;current++){
FP = (fEPoint)feP.get(current);
BP = (BasicPoint)FP.basic();
if(L.contains(BP)){
Z1 = FP.getZ();
Z2 = L.maxZfkt(BP);
if(Z2>0){
if(Z1==Z2)
result.setValue(3,true);
if(Z1>Z2)
result.setValue(4,true);
if(Z2>Z1)
result.setValue(5,true);
}
else { // Z2==0
result.setValue(1,true);
} // else
} // if
} // for
return result;
} // topolRelation
/** computes the fuzzy top. Relation between this and L */
public FuzzyTopRel topolRelation(FRegion R){
FuzzyTopRel result = new FuzzyTopRel();
int max = feP.getSize();
BasicPoint BP;
fEPoint FP;
double Z1,Z2;
for(int current=0; current<max;current++){
FP = (fEPoint)feP.get(current);
BP = (BasicPoint)FP.basic();
if(R.contains(BP)){
Z1 = FP.getZ();
Z2 = R.maxZfkt(BP);
if(Z2>0){
if(Z1==Z2)
result.setValue(3,true);
if(Z1>Z2)
result.setValue(4,true);
if(Z2>Z1)
result.setValue(5,true);
}
else { // Z2==0
result.setValue(1,true);
} // else
} // if
} // for
return result;
} // topolRelation
/** computes the topological relationship between this and CO */
public FuzzyTopRel topolRelation(CompositeObject CO){
if(CO instanceof FPoint)
return topolRelation((FPoint)CO);
if(CO instanceof FLine)
return topolRelation((FLine)CO);
if(CO instanceof FRegion)
return topolRelation((FRegion)CO);
return null;
}
/** returns the ListExpr representation of this FPoint
* (SF , (<PointList>))
*/
public ListExpr toListExpr(){
// first create the PointList
ListExpr Points;
ListExpr Last=null;
if(feP.getSize()==0)
Points = ListExpr.theEmptyList();
else {
Points = ListExpr.oneElemList(
((fEPoint)feP.get(0)).toListExpr());
Last = Points;
}
fEPoint NextPoint;
for(int i=1;i<feP.getSize();i++){
NextPoint = (fEPoint) feP.get(i);
Last=ListExpr.append(Last,NextPoint.toListExpr());
}
return ListExpr.twoElemList(
ListExpr.realAtom((float)SF),Points);
}
/** returns a String representation of
* the corresponding ListExpr
*/
public String toListString(){
return toListExpr().writeListExprToString();
}
/** creates a new ListEXpr <type,value>*/
public ListExpr toTypedListExpr(){
return ListExpr.twoElemList(
ListExpr.symbolAtom("fpoint"),toListExpr());
}
/** read the FPoint from a String representation of a ListExpr
* @return true if List is a String of a ListExpr containing
* a correct FPoint
*/
public boolean readFromListString(String List){
ListExpr LE = new ListExpr();
if(LE.readFromString(List)!=0){
return false;
}
else{
return readFromListExpr(LE);
}
}
/** compares two FPoints */
public int compareTo(FPoint P){
if(SF<P.SF)
return -1;
if(SF>P.SF)
return 1;
return feP.compareTo(P.feP);
}
/** read this FPoint from a ListExpr
* @return true if LE is a valid Representaion of a FPoint
* all valid Points of this List are insertet
*/
public boolean readFromListExpr(ListExpr LE){
SF = 1.0;
feP.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 Points = LE.second();
fEPoint P;
boolean ok = true;
while( !Points.isEmpty() & ok) {
P = new fEPoint(0,0,0);
if(P.readFromListExpr(Points.first())){
add(P);
Points=Points.rest();
}
else{
ok = false;
}
}
return ok;
}
/** this method is used for reading a fuzzy point from
* a byte array;
* returns null if the construction of the object failed
*/
public static FPoint readFrom(byte[] buffer){
try{
ObjectInputStream ois;
ois = new ObjectInputStream(
new ByteArrayInputStream(buffer));
FPoint res = (FPoint) 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(feP.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());
}
/** save the byte representation of this object in a file,
*for debugging only
*/
public void save(){
String FileName = "fpoint"+no;
try{
OutputStream out = new FileOutputStream(FileName);
byte[] content = writeToByteArray();
System.out.println("write "+content.length+
" bytes to "+FileName);
for(int i=0;i<content.length;i++){
out.write(content[i]);
}
out.flush();
out.close();
}catch(Exception e){
System.out.println("error in writing fpoint");
}
}
// 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;
private static int no = 0;
} // FPoint;