Logo Search packages:      
Sourcecode: carmetal version File versions

FixedAngleObject.java

/* 
Copyright 2006 Rene Grothmann, modified by Eric Hakenholz
This file is part of C.a.R. software.
C.a.R. is a 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, version 3 of the License.
C.a.R. 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package rene.zirkel.objects;

import java.awt.*;
import java.awt.event.*;
import java.util.*;

import rene.gui.*;
import rene.dialogs.*;
import rene.util.xml.*;
import rene.zirkel.Zirkel;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.ConstructionException;
import rene.zirkel.construction.Count;
import rene.zirkel.dialogs.EditConditionals;
import rene.zirkel.dialogs.ObjectEditDialog;
import rene.zirkel.expression.Expression;
import rene.zirkel.expression.InvalidException;
import rene.zirkel.graphics.MyGraphics;
import rene.zirkel.graphics.MyGraphics13;

class FixedAngleEditDialog extends ObjectEditDialog {

    TextField Length;
    Checkbox Fixed;
    IconBar SizeIB;
    ZirkelCanvas ZC;
    Button SetButton;

    public FixedAngleEditDialog(Frame f, FixedAngleObject o,
            ZirkelCanvas zc) {
        super(f, Zirkel.name("edit.angle.title"), o, "fixedangle");
        ZC=zc;
    }

    public void addFirst(Panel P) {
        FixedAngleObject o=(FixedAngleObject) O;
        Length=new TextFieldAction(this, "Length", o.getE());
        P.add(new MyLabel(Zirkel.name("edit.angle.length")));
        P.add(Length);
        Fixed=new Checkbox("");
        Fixed.setState(!o.isDragable());
        P.add(new MyLabel(Zirkel.name("edit.fixed")));
        P.add(Fixed);
    }

    public void doAction(String o) {
        if (o.equals("Length")&&Fixed!=null) {
            Fixed.setState(true);
            super.doAction("OK");
        } else if (o.equals("Set")) {
            ZC.set((FixedAngleObject) O);
            super.doAction("OK");
        } else {
            super.doAction(o);
        }
    }

    public void addSecond(Panel P) {
        FixedAngleObject p=(FixedAngleObject) O;
        SizeIB=new IconBar(F);
        SizeIB.addToggleGroupLeft("angle", 5);
        SizeIB.toggle("angle", p.getDisplaySize());
        SizeIB.addOnOffLeft("filled");
        SizeIB.setState("filled", p.isFilled());
        SizeIB.addOnOffLeft("obtuse");
        SizeIB.setState("obtuse", p.getObtuse());
        SizeIB.addOnOffLeft("inverse");
        SizeIB.setState("inverse", p.getInverse());
        SizeIB.addOnOffLeft("anglereduce");
        SizeIB.setState("anglereduce", p.isReduced());
        P.add(new MyLabel(""));
        P.add(SizeIB);
        SizeIB.setIconBarListener(this);
    }

    public void addButton(Panel P) {
        SetButton=new ButtonAction(this,
                Zirkel.name("edit.fixedangle.set"), "Set");
        P.add(SetButton);
    }

    public void iconPressed(String o) {
        if (o.equals("filled")) {
            if (SizeIB.getState("filled")) {
                IB.setState("isback", true);
            }
        }
        super.iconPressed(o);
    }

    public void setAction() {
        FixedAngleObject o=(FixedAngleObject) O;
        o.setObtuse(SizeIB.getState("obtuse"));
        o.setInverse(SizeIB.getState("inverse"));
        o.setReduced(SizeIB.getState("anglereduce"));
        o.setEditFixed(Length.getText());
        o.setDisplaySize(SizeIB.getToggleState("angle"));
        o.setFilled(SizeIB.getState("filled"));
        o.setDragable(!Fixed.getState());
    }

    public void focusGained(FocusEvent e) {
        if (Fixed!=null&&Fixed.getState()) {
            Length.requestFocus();
        } else {
            super.focusGained(e);
        }
    }
}

public class FixedAngleObject extends PrimitiveLineObject
        implements MoveableObject, SimulationObject, InsideObject {

    protected PointObject P2;
    static Count N=new Count();
    double A, A1, A2, AA;
    Expression E;
    boolean Filled=false;
    boolean Inverse=false;
    boolean EditAborted=false;
    boolean Dragable=false;
    boolean Reduced=false;
    public static final int NORMALSIZE=1,  SMALL=0,  LARGER=2,  LARGE=3,  RECT=4;
    protected int DisplaySize=NORMALSIZE;

    public FixedAngleObject(Construction c,
            PointObject p1, PointObject p2, double x, double y) {
        super(c);
        P1=p1;
        P2=p2;
        init(c, x, y);
        Unit=Global.getParameter("unit.angle", "");
    }

    public void setDefaults() {
        setShowName(Global.getParameter("options.angle.shownames", false));
        setShowValue(Global.getParameter("options.angle.showvalues", false));
        setColor(Global.getParameter("options.angle.color", 0));
        setColorType(Global.getParameter("options.angle.colortype", 0));
        setFilled(Global.getParameter("options.angle.filled", false));
        setHidden(Cn.Hidden);
        setObtuse(Global.getParameter("options.angle.obtuse", false));
        setSolid(Cn.Solid);
        setLarge(Cn.LargeFont);
        setBold(Cn.BoldFont);
        setPartial(Cn.Partial);
    }

    public void setTargetDefaults() {
        setShowName(Global.getParameter("options.angle.shownames", false));
        setShowValue(Global.getParameter("options.angle.showvalues", false));
        setColor(Global.getParameter("options.angle.color", 0));
        setColorType(Global.getParameter("options.angle.colortype", 0));
        setFilled(Global.getParameter("options.angle.filled", false));
        setObtuse(Global.getParameter("options.angle.obtuse", false));
    }

    public void init(Construction c, double x, double y, boolean invert) {
        double dx=P1.getX()-P2.getX(), dy=P1.getY()-P2.getY();
        A1=Math.atan2(dy, dx);
        dx=x-P2.getX();
        dy=y-P2.getY();
        A2=Math.atan2(dy, dx);
        A=A2-A1;
        if (A<0) {
            A+=2*Math.PI;
        } else if (A>2*Math.PI) {
            A-=2*Math.PI;
        }
        if (Inverse&&Obtuse) {
            A=2*Math.PI-A;
        }
        if (invert&&!Obtuse) {
            if (A>Math.PI) {
                A=2*Math.PI-A;
                Inverse=true;
            } else {
                Inverse=false;
            }
        }
        E=new Expression(""+round(A/Math.PI*180, ZirkelCanvas.EditFactor),
                c, this);
        validate();
        setColor(ColorIndex);
        updateText();
    }

    public void init(Construction c, double x, double y) {
        init(c, x, y, true);
    }
    double xx[]=new double[4], yy[]=new double[4];

    public void paint(MyGraphics g, ZirkelCanvas zc) {
        if (!Valid||mustHide(zc)) {
            return;
        }
        //compute middle of the screen:
        double xm=(zc.minX()+zc.maxX())/2, ym=(zc.minY()+zc.maxY())/2;
        // compute distance from middle to line:
        double d=(xm-X1)*DY-(ym-Y1)*DX;
        // compute point with minimal distance
        double x=xm-d*DY, y=ym+d*DX;
        // compute size of the screen
        double a=Math.max(zc.maxX()-zc.minX(), zc.maxY()-zc.minY());
        if (Math.abs(d)>a) {
            return;
        }
        // compute distance from closest point to source
        double b=(x-X1)*DX+(y-Y1)*DY;
        // compute the two visible endpoints
        double k1=b-a, k2=b+a;
        if (k1<0) {
            k1=0;
        }
        if (k1>=k2) {
            return;
        }
        double c1=zc.col(X1+k1*DX), c2=zc.col(X1+k2*DX),
                r1=zc.row(Y1+k1*DY), r2=zc.row(Y1+k2*DY);
        // paint:
        g.setColor(this);
        if (!Reduced) {
            g.drawLine(c1, r1, c2, r2, this);
        }
        double R=zc.col(getDisplaySize(zc))-zc.col(0);
        c1=zc.col(X1)-R;
        r1=zc.row(Y1)-R;
        String s=AngleObject.translateToUnicode(getDisplayText());
        double DA=(A/Math.PI*180);
        if (DA<0) {
            DA+=360;
        } else if (DA>=360) {
            DA-=360;
        }
        if (isStrongSelected()&&g instanceof MyGraphics13) {
            ((MyGraphics13) g).drawMarkerArc(c1+R, r1+R, R, A1/Math.PI*180, DA);
        }
        g.setColor(this);
        if (Filled) {
            if (Math.abs(DA-90)<0.0000001) {

                double dx1=Math.cos(A1), dy1=Math.sin(A1),
                        dx2=Math.cos(A1+DA/180*Math.PI), dy2=Math.sin(A1+DA/180*Math.PI);
                double dx3=dx1+dx2, dy3=dy1+dy2;
                xx[0]=c1;
                yy[0]=r1;
                xx[0]=c1+R;
                yy[0]=r1+R;
                xx[1]=c1+R+R*dx1;
                yy[1]=r1+R-R*dy1;
                xx[2]=c1+R+R*dx3;
                yy[2]=r1+R-R*dy3;
                xx[3]=c1+R+R*dx2;
                yy[3]=r1+R-R*dy2;
                g.fillPolygon(xx, yy, 4, false, getColorType()!=THICK, this);
                g.setColor(this);
                g.drawLine(xx[1], yy[1], xx[2], yy[2]);
                g.drawLine(xx[2], yy[2], xx[3], yy[3]);
            } else {
                g.fillArc(c1, r1, 2*R+1, 2*R+1, A1/Math.PI*180, DA,
                        Selected||getColorType()==NORMAL, getColorType()!=THICK, true, this);
            }

        } else {
            if (DisplaySize==RECT) {
                double dx1=Math.cos(A1), dy1=Math.sin(A1),
                        dx2=Math.cos(A1+DA/180*Math.PI), dy2=Math.sin(A1+DA/180*Math.PI);
                g.drawLine(c1+R+R*dx1, r1+R-R*dy1, c1+R+R*(dx1+dx2), r1+R-R*(dy1+dy2));
                g.drawLine(c1+R+R*(dx1+dx2), r1+R-R*(dy1+dy2), c1+R+R*dx2, r1+R-R*dy2);
            } else {

                if (Math.abs(DA-90)<0.0000001) {
                    double dx1=Math.cos(A1), dy1=Math.sin(A1),
                            dx2=Math.cos(A1+DA/180*Math.PI), dy2=Math.sin(A1+DA/180*Math.PI);
                    double dx3=dx1+dx2, dy3=dy1+dy2;
                    xx[1]=c1+R+R*dx1;
                    yy[1]=r1+R-R*dy1;
                    xx[2]=c1+R+R*dx3;
                    yy[2]=r1+R-R*dy3;
                    xx[3]=c1+R+R*dx2;
                    yy[3]=r1+R-R*dy2;
                    g.setColor(this);
                    g.drawLine(xx[1], yy[1], xx[2], yy[2]);
                    g.drawLine(xx[2], yy[2], xx[3], yy[3]);
                } else {
                    g.drawCircleArc(c1+R, r1+R, R, A1/Math.PI*180, DA, this);
                }



            }
        }
        if (!s.equals("")) {
            g.setLabelColor(this);
            setFont(g);
            DisplaysText=true;
            double dx=Math.cos(A1+A/2), dy=Math.sin(A1+A/2);
//            if (s.equals("90"+getUnit())||Name.startsWith(".")) {
//                if (KeepClose) {
//                    double dof=Math.sqrt(XcOffset*XcOffset+YcOffset*YcOffset);
//                    TX1=zc.col(X1+dof*dx)-3;
//                    TY1=zc.row(Y1+dof*dy)-3;
//                    TX2=TX1+9;
//                    TY2=TY1+9;
//                    g.drawRect(zc.col(X1+dof*dx)-1,
//                            zc.row(Y1+dof*dy)-1, 3, 3);
//                } else {
//                    TX1=zc.col(X1+zc.dx(R*AngleObject.LabelScale)*dx+XcOffset)-3;
//                    TY1=zc.row(Y1+zc.dy(R*AngleObject.LabelScale)*dy+YcOffset)-3;
//                    TX2=TX1+9;
//                    TY2=TY1+9;
//                    g.drawRect(zc.col(X1+zc.dx(R*AngleObject.LabelScale)*dx+XcOffset)-1,
//                            zc.row(Y1+zc.dy(R*AngleObject.LabelScale)*dy+YcOffset)-1, 3, 3);
//                }
//            } else {
            if (KeepClose) {
                double dof=Math.sqrt(XcOffset*XcOffset+YcOffset*YcOffset);
                drawCenteredLabel(g, s, zc,
                        X1+dof*dx, Y1+dof*dy, 0, 0);
            } else {
                drawCenteredLabel(g, s, zc,
                        X1+zc.dx(R*AngleObject.LabelScale)*dx,
                        Y1+zc.dy(R*AngleObject.LabelScale)*dy,
                        XcOffset, YcOffset);
            }
//            }
        }
    }

    public boolean canKeepClose() {
        return true;
    }

    public void setKeepClose(double x, double y) {
        KeepClose=true;
        XcOffset=x-X1;
        YcOffset=y-Y1;
    }

    double getDisplaySize(ZirkelCanvas zc) {
        double R=zc.dx((int) (12*zc.pointSize()));
        if (DisplaySize==SMALL||DisplaySize==RECT) {
            R/=2;
        } else if (DisplaySize==LARGER) {
            R*=2;
        } else if (DisplaySize==LARGE) {
            double dx=P1.getX()-X1, dy=P1.getY()-Y1;
            R=Math.sqrt(dx*dx+dy*dy);
        }
        return R;
    }

    public String getTag() {
        return "Angle";
    }

    public int getN() {
        return N.next();
    }

    public void updateText() {
        if (E==null||!E.isValid()) {
            return;
        }
        setText(text3(Zirkel.name("text.fixedangle"),
                P1.getName(), P2.getName(), E.toString()));
    }

    public String getDisplayValue() {
        if (ZirkelCanvas.AnglesFactor<=2) {
            return ""+(int) (A/Math.PI*180+0.5);
        } else {
            return ""+round(A/Math.PI*180, ZirkelCanvas.AnglesFactor);
        }
    }

    public void validate() {
        if (!P1.valid()||!P2.valid()) {
            Valid=false;
            return;
        } else {
            X1=P2.getX();
            Y1=P2.getY();
            double dx=P1.getX()-X1, dy=P1.getY()-Y1;
            if (Math.sqrt(dx*dx+dy*dy)<1e-9) {
                Valid=false;
                return;
            }
            A1=Math.atan2(dy, dx);
            boolean Negative=false;
            try {
                if (E!=null&&E.isValid()) {
                    A=E.getValue()/180*Math.PI;
                }
                if (Obtuse) {
                    if (Inverse) {
                        A=-A;
                    }
                } else {
                    if (Inverse&&Math.sin(A)>0) {
                        A=-A;
                    }
                    if (!Inverse&&Math.sin(A)<0) {
                        A=-A;
                    }
                }
                if (A<0) {
                    Negative=true;
                }
                while (A<0) {
                    A=A+2*Math.PI;
                }
                while (A>=2*Math.PI) {
                    A=A-2*Math.PI;
                }
                A2=A1+A;
                DX=Math.cos(A2);
                DY=Math.sin(A2);
                AA=A;
            } catch (Exception e) {
                Valid=false;
                return;
            }
            if (!Obtuse&&A>Math.PI) {
                A1=A2;
                A=2*Math.PI-A;
                A2=A1+A;
            } else if (Obtuse&&Negative) {
                A1=A2;
                A=2*Math.PI-A;
                A2=A1+A;
            }
            Valid=true;
        }
    }

    public double getLength() {
        return A;
    }

    public void setFixed(String s) {
        E=new Expression(s, getConstruction(), this);
        updateText();
    }

    public void round() {
        try {
            setFixed(round(E.getValue(), ZirkelCanvas.AnglesFactor)+"");
            validate();
        } catch (Exception e) {
        }
    }

    public void setEditFixed(String s) {
        E=new Expression(s, getConstruction(), this);
        updateText();
    }

    public boolean canFix() {
        return true;
    }

    public void printArgs(XmlWriter xml) {
        xml.printArg("first", P1.getName());
        xml.printArg("root", P2.getName());
        if (DisplaySize==SMALL) {
            xml.printArg("display", "small");
        }
        if (DisplaySize==LARGE) {
            xml.printArg("display", "large");
        }
        if (DisplaySize==LARGER) {
            xml.printArg("display", "larger");
        }
        if (DisplaySize==RECT) {
            xml.printArg("display", "rectangle");
        }
        if (Filled) {
            xml.printArg("filled", "true");
        }
        if (E.isValid()) {
            xml.printArg("fixed", E.toString());
        } else {
            xml.printArg("fixed", ""+A/Math.PI*180);
        }
        if (!Obtuse) {
            xml.printArg("acute", "true");
        }
        if (Inverse) {
            xml.printArg("inverse", "true");
        }
        if (Reduced) {
            xml.printArg("reduced", "true");
        }
        if (Dragable) {
            xml.printArg("dragable", "true");
        }
        super.printArgs(xml);
    }

    public void edit(ZirkelCanvas zc) {
        ObjectEditDialog d;
        if (!rene.zirkel.Zirkel.IsApplet) {
            eric.JGlobals.EditObject(this);
            return;
        }
        while (true) {
            d=new FixedAngleEditDialog(zc.getFrame(), this, zc);
            d.setVisible(true);
            zc.repaint();
            EditAborted=false;
            if (d.isAborted()) {
                EditAborted=true;
                break;
            } else if (E!=null&&!E.isValid()) {
                Frame F=zc.getFrame();
                Warning w=new Warning(F, E.getErrorText(),
                        Zirkel.name("warning"), true);
                w.center(F);
                w.setVisible(true);
            } else {
                break;
            }
        }
        if (d.wantsMore()) {
            new EditConditionals(zc.getFrame(), this);
            validate();
        }
    }

    public boolean nearto(int c, int r, ZirkelCanvas zc) {
        if (!Valid&&P2.valid()) {
            return P2.nearto(c, r, zc);
        }
        if (!displays(zc)) {
            return false;
        }
        //compute point at c,r
        double x=zc.x(c), y=zc.y(r);
        // compute distance from x,y
        double d=(x-X1)*DY-(y-Y1)*DX;
        double e=(x-X1)*DX+(y-Y1)*DY;
        // scale in screen coordinates
        Value=Math.abs(zc.col(zc.minX()+d)-zc.col(zc.minX()));
        if (!Reduced&&Value<zc.selectionSize()&&e>0) {
            return true;
        }
        double dx=zc.x(c)-X1, dy=zc.y(r)-Y1;
        double size=zc.dx((int) zc.selectionSize());
        double rd=getDisplaySize(zc);
        double rr=Math.sqrt(dx*dx+dy*dy);
        boolean near;
        if (Filled||DisplaySize==RECT) {
            near=(rr<rd+size);
        } else {
            near=(Math.abs(rr-rd)<size);
        }
        if (!near) {
            return false;
        }
        if (rd<size) {
            return near;
        }
        double a=Math.atan2(dy, dx);
        if (a<0) {
            a+=2*Math.PI;
        }
        double cc=0.05;
        if (A1-cc<a&&A2+cc>a) {
            return true;
        }
        a=a-2*Math.PI;
        if (A1-cc<a&&A2+cc>a) {
            return true;
        }
        a=a+4*Math.PI;
        if (A1-cc<a&&A2+cc>a) {
            return true;
        }
        return false;
    }

    public void setDisplaySize(int i) {
        DisplaySize=i;
    }

    public int getDisplaySize() {
        return DisplaySize;
    }

    public Enumeration depending() {
        super.depending();
        depset(P1, P2);
        Enumeration e=E.getDepList().elements();
        while (e.hasMoreElements()) {
            DL.add((ConstructionObject) e.nextElement());
        }
        return DL.elements();
    }

    public void translate() {
        P1=(PointObject) P1.getTranslation();
        P2=(PointObject) P2.getTranslation();
        try {
            setFixed(E.toString());
            E.translate();
        } catch (Exception e) {
        }
    }

    public String getE() {
        return E.toString();
    }

    public double getValue()
            throws ConstructionException {
        if (!Valid) {
            throw new InvalidException("exception.invalid");
        } else {
            return A/Math.PI*180;
        }
    }

    public void setFilled(boolean flag) {
        Filled=flag;
    }

    public boolean isFilled() {
        return Filled;
    }

    public boolean isFilledForSelect() {
        return false;
    }

    public boolean contains(double x, double y) {
        double a=(x-X1)*DX+(y-Y1)*DY;
        if (a<1e-9) {
            return false;
        }
        return true;
    }

    public double project(double x, double y) {
        double h=super.project(x, y);
        if (h<0) {
            return 0;
        }
        return h;
    }

    public Enumeration points() {
        super.depending();
        return depset(P2);
    }

    public void move(double x, double y) {
        init(getConstruction(), x, y, true);
    }

    public boolean moveable() {
        return Dragable; // E.isNumber();
    }

    public boolean isFixed() {
        return true;
    }

    public boolean getInverse() {
        return Inverse;
    }

    public void setInverse(boolean inverse) {
        Inverse=inverse;
    }

    public boolean isEditAborted() {
        return EditAborted;
    }

    public boolean isDragable() {
        return Dragable;
    }

    public void setDragable(boolean f) {
        Dragable=f;
    }

    public boolean isReduced() {
        return Reduced;
    }

    public void setReduced(boolean f) {
        Reduced=f;
    }

    public boolean fixedByNumber() {
        return (E!=null&&E.isNumber());
    }

    // For the simulate function:
    /**
     * Set the simulation value, remember the old value.
     */
    public void setSimulationValue(double x) {
        A=x/180*Math.PI;
        Expression OldE=E;
        E=null;
        validate();
        E=OldE;
    }

    /**
     * Reset the old value.
     */
    public void resetSimulationValue() {
        validate();
    }

    public void startDrag(double x, double y) {
    }

    public void dragTo(double x, double y) {
        move(x, y);
    }

    public double getOldX() {
        return 0;
    }

    public double getOldY() {
        return 0;
    }

    public double containsInside(PointObject P) {
        double dx=P.getX()-X1, dy=P.getY()-Y1;
        double a=Math.atan2(dy, dx);
        if (a<A1) {
            a+=2*Math.PI;
        }
        double c=1e-5;
        if (a>A1&&a<A1+A) {
            return 1;
        } else if (a>A1-c&&a<A1+A+c) {
            return 0.5;
        }
        return 0;
    }

    public boolean keepInside(PointObject P) {
        if (containsInside(P)>0) {
            return true;
        }
        double x=P.getX(), y=P.getY();
        double x1=X1, y1=Y1;
        double xmin=x1, ymin=y1, dmin=1e20;
        double x2=X1+Math.cos(A1), y2=Y1+Math.sin(A1);
        double dx=x2-x1, dy=y2-y1;
        double r=dx*dx+dy*dy;
        double h=dx*(x-x1)/r+dy*(y-y1)/r;
        if (h<0) {
            h=0;
        }
        double xh=x1+h*dx, yh=y1+h*dy;
        double dist=Math.sqrt((x-xh)*(x-xh)+(y-yh)*(y-yh));
        if (dist<dmin) {
            dmin=dist;
            xmin=xh;
            ymin=yh;
        }
        x2=X1+Math.cos(A2);
        y2=Y1+Math.sin(A2);
        dx=x2-x1;
        dy=y2-y1;
        r=dx*dx+dy*dy;
        h=dx*(x-x1)/r+dy*(y-y1)/r;
        if (h<0) {
            h=0;
        }
        xh=x1+h*dx;
        yh=y1+h*dy;
        dist=Math.sqrt((x-xh)*(x-xh)+(y-yh)*(y-yh));
        if (dist<dmin) {
            dmin=dist;
            xmin=xh;
            ymin=yh;
        }
        P.move(xmin, ymin);
        return false;
    }
}

Generated by  Doxygen 1.6.0   Back to index