461 lines
14 KiB
Java
461 lines
14 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 viewer.hoese.algebras;
|
||
|
|
|
||
|
|
import java.awt.geom.*;
|
||
|
|
import java.awt.*;
|
||
|
|
import sj.lang.ListExpr;
|
||
|
|
import java.util.*;
|
||
|
|
import viewer.*;
|
||
|
|
import viewer.hoese.*;
|
||
|
|
import tools.Reporter;
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The displayclass of the Constraint algebras constraint datatype.
|
||
|
|
*/
|
||
|
|
public class Dsplconstraint extends DisplayGraph {
|
||
|
|
/** The internal datatype representation */
|
||
|
|
Area areaPolygons;
|
||
|
|
Point2D.Double[] arrPoints;
|
||
|
|
Rectangle2D.Double bounds;
|
||
|
|
GeneralPath GPLines;
|
||
|
|
|
||
|
|
/** Returns the number of shapes **/
|
||
|
|
public int numberOfShapes(){
|
||
|
|
return 3;
|
||
|
|
}
|
||
|
|
|
||
|
|
public boolean isPointType(int num){
|
||
|
|
return (num==2);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Returns true if the render object is a line **/
|
||
|
|
public boolean isLineType(int num){
|
||
|
|
return (num==1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns the shape of the objects in order to render it
|
||
|
|
*/
|
||
|
|
public Shape getRenderObject(int num,AffineTransform at){
|
||
|
|
if(num==0)
|
||
|
|
{
|
||
|
|
return areaPolygons;
|
||
|
|
} else if(num==1){
|
||
|
|
return GPLines;
|
||
|
|
} else if(num==2){
|
||
|
|
Area res = null;
|
||
|
|
double ps = Cat.getPointSize(renderAttribute,
|
||
|
|
CurrentState.ActualTime);
|
||
|
|
double pixx = Math.abs(ps/at.getScaleX());
|
||
|
|
double pixy = Math.abs(ps/at.getScaleY());
|
||
|
|
for(int i=0; i< arrPoints.length;i++)
|
||
|
|
{
|
||
|
|
Area tmp = null;
|
||
|
|
if(Cat.getPointasRect())
|
||
|
|
{
|
||
|
|
tmp=(new Area(new Rectangle2D.Double(
|
||
|
|
arrPoints[i].x-pixx/2,
|
||
|
|
arrPoints[i].y-pixy/2,pixx,pixy)));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
tmp=(new Area(new Ellipse2D.Double(
|
||
|
|
arrPoints[i].x-pixx/2,
|
||
|
|
arrPoints[i].y-pixy/2,pixx,pixy)));
|
||
|
|
}
|
||
|
|
if(res==null){
|
||
|
|
res = tmp;
|
||
|
|
}else{
|
||
|
|
res.add(tmp);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return res;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Scans the external representation of a constraint datatype
|
||
|
|
*/
|
||
|
|
private void ScanValue (ListExpr v) {
|
||
|
|
|
||
|
|
boolean correct = true;
|
||
|
|
ListExpr symbolicTuplesNL = v;
|
||
|
|
ListExpr linConstraintsNL;
|
||
|
|
ListExpr oneLinConstraintNL;
|
||
|
|
|
||
|
|
boolean emptyPolygons = true;
|
||
|
|
boolean emptyLines = true;
|
||
|
|
boolean emptyPoints = true;
|
||
|
|
Vector vecPoints = new Vector();
|
||
|
|
|
||
|
|
areaPolygons = new Area();
|
||
|
|
GPLines = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
|
||
|
|
|
||
|
|
if(!v.isAtom())
|
||
|
|
{
|
||
|
|
while(!symbolicTuplesNL.isEmpty())
|
||
|
|
{
|
||
|
|
linConstraintsNL = symbolicTuplesNL.first();
|
||
|
|
symbolicTuplesNL = symbolicTuplesNL.rest();
|
||
|
|
if(!linConstraintsNL.isAtom())
|
||
|
|
{
|
||
|
|
Shape geoObject;
|
||
|
|
|
||
|
|
Vector vLinConstraints = new Vector();
|
||
|
|
int nrOfCEQ = 0;
|
||
|
|
int currentIndex = 0;
|
||
|
|
int firstIndexCEQ = -1;
|
||
|
|
int secondIndexCEQ = -1;
|
||
|
|
while(!linConstraintsNL.isEmpty())
|
||
|
|
{
|
||
|
|
oneLinConstraintNL = linConstraintsNL.first();
|
||
|
|
linConstraintsNL = linConstraintsNL.rest();
|
||
|
|
if(oneLinConstraintNL.listLength() == 4 &&
|
||
|
|
oneLinConstraintNL.first().atomType() ==
|
||
|
|
ListExpr.REAL_ATOM &&
|
||
|
|
oneLinConstraintNL.second().atomType() ==
|
||
|
|
ListExpr.REAL_ATOM &&
|
||
|
|
oneLinConstraintNL.third().atomType() ==
|
||
|
|
ListExpr.REAL_ATOM &&
|
||
|
|
oneLinConstraintNL.fourth().atomType() ==
|
||
|
|
ListExpr.SYMBOL_ATOM)
|
||
|
|
{
|
||
|
|
Double a1 = LEUtils.readNumeric(
|
||
|
|
oneLinConstraintNL.first());
|
||
|
|
Double a2 = LEUtils.readNumeric(
|
||
|
|
oneLinConstraintNL.second());
|
||
|
|
Double b = LEUtils.readNumeric(
|
||
|
|
oneLinConstraintNL.third());
|
||
|
|
String strOp =
|
||
|
|
oneLinConstraintNL.fourth().symbolValue();
|
||
|
|
|
||
|
|
LinearConstraint2D linConstraint =
|
||
|
|
new LinearConstraint2D(
|
||
|
|
a1.doubleValue(),
|
||
|
|
a2.doubleValue(),
|
||
|
|
b.doubleValue(),
|
||
|
|
strOp);
|
||
|
|
vLinConstraints.addElement(linConstraint);
|
||
|
|
if(linConstraint.strOp.equals("eq"))
|
||
|
|
{
|
||
|
|
nrOfCEQ++;
|
||
|
|
if(firstIndexCEQ==-1)
|
||
|
|
{
|
||
|
|
firstIndexCEQ = currentIndex;
|
||
|
|
}
|
||
|
|
else if(secondIndexCEQ==-1)
|
||
|
|
{
|
||
|
|
secondIndexCEQ = currentIndex;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// then there are more than 2 EQ-constraints,
|
||
|
|
// what is a contradiction to the normalization!
|
||
|
|
Reporter.writeError("Error: Too many EQ-constraint!");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Reporter.writeError("Error: Wrong format"+
|
||
|
|
" of lin.constraint!");
|
||
|
|
}
|
||
|
|
currentIndex++;
|
||
|
|
}
|
||
|
|
// The number of eq-constraints determines
|
||
|
|
// the type of the shape:
|
||
|
|
if(nrOfCEQ==0)
|
||
|
|
{
|
||
|
|
// convex polygon:
|
||
|
|
emptyPolygons = false;
|
||
|
|
GeneralPath GPPolygon = new GeneralPath(
|
||
|
|
GeneralPath.WIND_EVEN_ODD);
|
||
|
|
for(int i=0; i < vLinConstraints.size(); i++)
|
||
|
|
{
|
||
|
|
Point2D.Double point;
|
||
|
|
if(i==0)
|
||
|
|
{
|
||
|
|
point = GetIntersectionPoint((LinearConstraint2D)
|
||
|
|
vLinConstraints.lastElement(),
|
||
|
|
(LinearConstraint2D)vLinConstraints.firstElement());
|
||
|
|
try{
|
||
|
|
if(!ProjectionManager.project(
|
||
|
|
point.x,point.y,aPoint)){
|
||
|
|
Reporter.writeError("error in projection at ("+
|
||
|
|
point.x+", "+point.y+")");
|
||
|
|
err=true;
|
||
|
|
return;
|
||
|
|
}else{
|
||
|
|
GPPolygon.moveTo((float)point.x, (float)point.y);
|
||
|
|
}
|
||
|
|
}catch(Exception e){
|
||
|
|
Reporter.writeError("Error in Projection at ("+
|
||
|
|
point.x+","+point.y+")");
|
||
|
|
err=true;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
point = GetIntersectionPoint(
|
||
|
|
(LinearConstraint2D)vLinConstraints.elementAt(i-1),
|
||
|
|
(LinearConstraint2D)vLinConstraints.elementAt(i));
|
||
|
|
try{
|
||
|
|
if(!ProjectionManager.project(
|
||
|
|
point.x,point.y,aPoint)){
|
||
|
|
Reporter.writeError("error in projection at ("+
|
||
|
|
point.x+", "+point.y+")");
|
||
|
|
err=true;
|
||
|
|
return;
|
||
|
|
}else{
|
||
|
|
GPPolygon.lineTo((float)point.x, (float)point.y);
|
||
|
|
}
|
||
|
|
}catch(Exception e){
|
||
|
|
Reporter.writeError("Error in Projection at ("+
|
||
|
|
point.x+","+point.y+")");
|
||
|
|
err=true;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
GPPolygon.closePath();
|
||
|
|
areaPolygons.add(new Area(GPPolygon));
|
||
|
|
}
|
||
|
|
else if(nrOfCEQ==1)
|
||
|
|
{
|
||
|
|
// line segment:
|
||
|
|
emptyLines = false;
|
||
|
|
// the EQ-constraint is the very first
|
||
|
|
Point2D.Double pointFirst = GetIntersectionPoint(
|
||
|
|
(LinearConstraint2D)vLinConstraints.elementAt(0),
|
||
|
|
(LinearConstraint2D)vLinConstraints.elementAt(1));
|
||
|
|
Point2D.Double pointSecond = GetIntersectionPoint(
|
||
|
|
(LinearConstraint2D)vLinConstraints.elementAt(0),
|
||
|
|
(LinearConstraint2D)vLinConstraints.elementAt(2));
|
||
|
|
try{
|
||
|
|
if(!ProjectionManager.project(pointFirst.x,
|
||
|
|
pointFirst.y,aPoint)){
|
||
|
|
Reporter.writeError("error in projection at ("+
|
||
|
|
pointFirst.x+", "+pointFirst.y+")");
|
||
|
|
err=true;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
else{
|
||
|
|
GPLines.moveTo((float)pointFirst.x,
|
||
|
|
(float)pointFirst.y);
|
||
|
|
}
|
||
|
|
}catch(Exception e){
|
||
|
|
Reporter.writeError("Error in Projection at ("+
|
||
|
|
pointFirst.x+","+pointFirst.y+")");
|
||
|
|
err=true;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
try{
|
||
|
|
if(!ProjectionManager.project(pointSecond.x,
|
||
|
|
pointSecond.y,aPoint)){
|
||
|
|
Reporter.writeError("error in projection at ("+
|
||
|
|
pointSecond.x+", "+pointSecond.y+")");
|
||
|
|
err=true;
|
||
|
|
return;
|
||
|
|
}else{
|
||
|
|
GPLines.lineTo((float)pointSecond.x,
|
||
|
|
(float)pointSecond.y);
|
||
|
|
}
|
||
|
|
}catch(Exception e){
|
||
|
|
Reporter.writeError("Error in Projection at ("+
|
||
|
|
pointSecond.x+","+pointSecond.y+")");
|
||
|
|
err=true;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if(nrOfCEQ==2)
|
||
|
|
{
|
||
|
|
// point:
|
||
|
|
emptyPoints = false;
|
||
|
|
Point2D.Double point = GetIntersectionPoint(
|
||
|
|
(LinearConstraint2D)vLinConstraints.elementAt(0),
|
||
|
|
(LinearConstraint2D)vLinConstraints.elementAt(1));
|
||
|
|
try{
|
||
|
|
if(!ProjectionManager.project(point.x,point.y,aPoint)){
|
||
|
|
Reporter.writeError("error in projection at ("+
|
||
|
|
point.x+", "+point.y+")");
|
||
|
|
err=true;
|
||
|
|
return;
|
||
|
|
}else{
|
||
|
|
vecPoints.addElement(point);
|
||
|
|
}
|
||
|
|
}catch(Exception e){
|
||
|
|
Reporter.writeError("Error in Projection at ("+
|
||
|
|
point.x+","+point.y+")");
|
||
|
|
err=true;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Reporter.writeError("Error: nrOfCEQ to big!");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Reporter.writeError("Error: linConstraintsNL is atomic");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Reporter.writeError("Error: instance is atomic "+
|
||
|
|
"(shoud be a list!)");
|
||
|
|
}
|
||
|
|
|
||
|
|
if(emptyPolygons)
|
||
|
|
{
|
||
|
|
areaPolygons = null;
|
||
|
|
}
|
||
|
|
if(emptyLines)
|
||
|
|
{
|
||
|
|
GPLines = null;
|
||
|
|
}
|
||
|
|
arrPoints = (Point2D.Double[])vecPoints.toArray(
|
||
|
|
new Point2D.Double[0]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Init. the Dsplconstraint instance.
|
||
|
|
*/
|
||
|
|
public void init (String name, int nameWidth, int indent,
|
||
|
|
ListExpr type, ListExpr value, QueryResult qr) {
|
||
|
|
AttrName = extendString(name, nameWidth, indent);
|
||
|
|
ScanValue(value);
|
||
|
|
if (err) {
|
||
|
|
Reporter.writeError("Error in ListExpr :parsing aborted");
|
||
|
|
qr.addEntry(new String("(" + AttrName + ": GA(constraint))"));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
qr.addEntry(this);
|
||
|
|
bounds = null;
|
||
|
|
if(areaPolygons!=null)
|
||
|
|
{
|
||
|
|
bounds = new Rectangle2D.Double();
|
||
|
|
bounds.setRect(areaPolygons.getBounds2D());
|
||
|
|
}
|
||
|
|
if(GPLines!=null)
|
||
|
|
{
|
||
|
|
if (bounds == null)
|
||
|
|
{
|
||
|
|
bounds = new Rectangle2D.Double();
|
||
|
|
bounds.setRect(GPLines.getBounds2D());
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
bounds = (Rectangle2D.Double)bounds.createUnion(
|
||
|
|
GPLines.getBounds2D());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for(int i=0; i< arrPoints.length;i++)
|
||
|
|
{
|
||
|
|
if (bounds == null)
|
||
|
|
bounds = new Rectangle2D.Double(arrPoints[i].x,
|
||
|
|
arrPoints[i].y, 0, 0);
|
||
|
|
else
|
||
|
|
bounds = (Rectangle2D.Double)bounds.createUnion(
|
||
|
|
new Rectangle2D.Double(arrPoints[i].x,
|
||
|
|
arrPoints[i].y, 0, 0));
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Returns the minimum bounding box **/
|
||
|
|
public Rectangle2D.Double getBounds () {
|
||
|
|
return bounds;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns the intersection point of two linear constraints
|
||
|
|
* (seen as equivalation)
|
||
|
|
* Prerequisite: not parallel or equal
|
||
|
|
* (otherwise they woudn't intersection in one point)
|
||
|
|
*/
|
||
|
|
Point2D.Double GetIntersectionPoint(
|
||
|
|
final LinearConstraint2D linConFirst,
|
||
|
|
final LinearConstraint2D linConSecond)
|
||
|
|
{
|
||
|
|
boolean blnIsPoint;
|
||
|
|
Point2D.Double pIntersection;
|
||
|
|
double x, y;
|
||
|
|
|
||
|
|
try {
|
||
|
|
x = (linConFirst.a2*linConSecond.b-
|
||
|
|
linConSecond.a2*linConFirst.b)/
|
||
|
|
(linConFirst.a1*linConSecond.a2-
|
||
|
|
linConSecond.a1*linConFirst.a2);
|
||
|
|
y = (linConFirst.a1*linConSecond.b-
|
||
|
|
linConSecond.a1*linConFirst.b)/
|
||
|
|
(linConFirst.a2*linConSecond.a1-
|
||
|
|
linConSecond.a2*linConFirst.a1);
|
||
|
|
pIntersection = new Point2D.Double(x,y);
|
||
|
|
}
|
||
|
|
catch (Exception e) {
|
||
|
|
Reporter.writeError("Error: GetIntersectionPoint can't compute a "+
|
||
|
|
"single intersecting point - invalid input (lin. constraints "+
|
||
|
|
"describes parallel lines)!");
|
||
|
|
pIntersection = new Point2D.Double(0,0);
|
||
|
|
}
|
||
|
|
return pIntersection;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Datastructure for the internal repr. of a lin. constraint **/
|
||
|
|
class LinearConstraint2D
|
||
|
|
{
|
||
|
|
public double a1;
|
||
|
|
public double a2;
|
||
|
|
public double b;
|
||
|
|
public String strOp;
|
||
|
|
|
||
|
|
LinearConstraint2D()
|
||
|
|
{
|
||
|
|
a1 = 0;
|
||
|
|
a2 = 0;
|
||
|
|
b = 0;
|
||
|
|
strOp = new String("eq");
|
||
|
|
}
|
||
|
|
|
||
|
|
LinearConstraint2D(double a1, double a2, double b, String strOp)
|
||
|
|
{
|
||
|
|
this.a1 = a1;
|
||
|
|
this.a2 = a2;
|
||
|
|
this.b = b;
|
||
|
|
this.strOp = strOp;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|