//***************************************************************************** // // Beenish Chaudry, Geetika Tewari, Elif Tosun and // Ileana Streinu // // Summer 1999, Fall 1999, Spring 2000 // //***************************************************************************** // // PointObj.java // // Extends the class Point with: // // appearance: shape, color, contour, fill, visibility // label // relative coordinates // location of label and coordinates // // dual line appearance // // selected // //***************************************************************************** import java.awt.*; import java.awt.event.*; import java.lang.*; import java.io.*; import java.util.*; import java.math.*; public class PointObj extends Point { //******************************* // // Instance Variables // //****************************** // coordinates relative to the current frame of reference Rational rx, ry; // the relative values of x and y // location on screen of auxiliary information - label, coordinates, equation Point LocLabelP; // location of point label - as displacement Point LocCoordP; // location of the displayed coordinates - as displacement Point LocLabelL; // location of line label, as hook point on the line Point LocEqL; // location of the displayed equation - hook pt on line Point hookN; // hooks for drawing the line Point hookS; // labels int linsert; // label, insert order - the id of the point int lxcoord; // label, xcoord order // Point appearance: // // shape: circle, square, small or big. // fill: filled or not, and what color // contour: with contour or not, and what color // visible: degree of visibility // userLabel: user label PointAppearance appearanceP; // int shape; // int fill; // Color fillcolor; // Color contcolor; // boolean contour; // int visible; // String userLabel // int wCoord; // dual line properties LineAppearance appearanceL; // selected int selected; //******************************* // // PointObj constructor // //****************************** public PointObj(){ super(); x = y = 0; rx = new Rational(0, 1); ry = new Rational(0, 1); LocLabelP = new Point(0,0); LocCoordP = new Point(0,0); LocLabelL = new Point(0,0); LocEqL = new Point(0,0); hookN = new Point(0,0); hookS = new Point(0,0); linsert = 0; // a "real" label has to be computed here lxcoord = 0; // a "real" label has to be computed here appearanceP = new PointAppearance(); appearanceL = new LineAppearance(); selected = StateSelect.not; }// end PointObj constructor //******************************* // // Duplicate // // copies the point into a new one // (all variables except the labels) // //****************************** public PointObj Duplicate() { PointObj p = new PointObj(); p.x = x; p.y = y; p.rx = rx; p.ry = ry; p.appearanceP.Copy(appearanceP); p.appearanceL.Copy(appearanceL); p.linsert = linsert; p.lxcoord = lxcoord; p.selected = selected; return(p); } //******************************* // // setPointCoord // //****************************** public void setPointCoord(Point p) { x = p.x; y = p.y; } //******************************* // // Reset // //****************************** public void Reset() { x = y = 0; rx = new Rational(0, 1); ry = new Rational(0, 1); linsert = 0; // a "real" label has to be computed here lxcoord = 0; // a "real" label has to be computed here selected = StateSelect.not; appearanceP.Reset(); appearanceL.Reset(); }//end Reset //**************************** // // LEquals myObject // Loose Equality of objects // //**************************** public boolean LEquals(PointObj obj) { if (( x-obj.x > -6) && ( x - obj.x < 6) && ( y-obj.y > -6) && ( y - obj.y < 6)) return true; else return false; } //*********************** // // MoveSelPoint // // move a selected point with arrow keys // //*********************** public void MoveSelPoint(FramePoint bf, int key, Point or, boolean wOrient, Rational unitL) { switch(key) { case Constants.LEFT: x--; break; case Constants.RIGHT: x++; break; case Constants.UP: y--; break; case Constants.DOWN: y++; break; default: } AbsToRel(or, wOrient, unitL); UpdateLabel(); UpdateHooks(bf); // update xcoord label - Ileana ??? }// end MoveSelPoint //******************************************** // // MoveLabelPoint // move the location of the label of a point // //********************************************* public void MoveLabelPoint(Point p) { // update displacement of location of label // parameter p gives location of mouse click for // new location of label, and we compute and // store the displacement LocLabelP.x = p.x - x; LocLabelP.y = p.y - y; }// end MoveLabelPoint //******************************************** // // MoveCoordPoint // move the location of the printing of coordinates // for a point // //********************************************* public void MoveCoordPoint(Point p) { // update displacement of location of coordinates // same philosophy as above, for Label LocCoordP.x = p.x - x; LocCoordP.y = p.y - y; }// end MoveCoordPoint //******************************************** // // MoveLabelLine // move the location of the label of a line // //********************************************* public void MoveLabelLine(Point p) { // update location of label // find closest to p point on dual line // LocLabelL.x = p.x; // LocLabelL.y = p.y; // ??? to work on }// end MoveLabelLine //******************************************** // // MoveEqLine // move the location of the printing of coordinates // for a point // //********************************************* public void MoveEqLine(Point p) { // update location of equation // to a closest to p point on dual line // LocEqL.x = p.x; // LocEqL.y = p.y; // ??? to work on }// end MoveEqLine //******************************* // // Auxiliary functions, used in InfoFrame: // // ToStringAbsolute // ToStringRelative // //****************************** public String ToStringAbsolute() { return("\n " + linsert + ":Abs(" + x + "," + y + ")\n"); } // ToStringAbs public String ToStringRelative() { return(" Rel ((" + rx.n + ", " + rx.d + "), (" + ry.n + ", " + ry.d + "))\n"); }//end of ToStringRelative //******************************* // // UpdateLabel // // update the labels after changes // //****************************** public void UpdateLabel() { // ??? to work on - decide how to assign new id's for point labels //System.out.println("In UpdateLabel for PointObj"); }// end UpdateLabel //******************************* // // UpdateHooks // // update the hooks of a dual line // //****************************** public void UpdateHooks(FramePoint bf) { // compute hooks for drawing line and use them to initialize // label and coordinate location for dual line ComputeLineHooks(bf.width, bf.height, bf.ps.or, bf.ps.wOrient, bf.ps.unitL, bf.lf.duality, hookN, hookS); LocLabelL.x = hookN.x; LocLabelL.y = hookN.y; LocEqL.x = hookS.x; LocEqL.y = hookS.y; System.out.println("hookN.x=" + hookN.x); System.out.println("hookN.y=" + hookN.y); System.out.println("hookS.x=" + hookS.x); System.out.println("hookS.y=" + hookS.y); } // end UpdateHooks //******************************* // // AbsToRel // // using the frame of reference, computes the relative // from the absolute coordinates // //****************************** public void AbsToRel (Point or, boolean wOrient, Rational unitL) { /* uses x & y coord of pt.*/ /* modifies rx, ry */ /* depends on crtOrigin & crt Zoom factor - unit length */ /* called on mouse click and whenever the relative coord change */ // !!!!!!!!!! // // check where else it is called - Ileana // rx = new Rational(((x-or.x)*unitL.d), unitL.n); ry = new Rational(((y-or.y)*unitL.d), unitL.n); if(wOrient) ry.n = - ry.n; } //end AbstoRel //******************************************** // // InitLocLabelP // initialize LocLabel and LocCoord // //********************************************* public void InitLocLabelP() { // set displacement of location of label and coordinates LocLabelP.x = Constants.locLabelX; LocLabelP.y = Constants.locLabelY; LocCoordP.x = Constants.locCoordX; LocCoordP.y = Constants.locCoordY; // compute point on dual line // need duality used, relative coord - quite a lot /* // ??? to work on // next, superfluous, as we need only a point on dual line // LocLabelL.x = ptOnLineL.x + Constants.locLabelLX; // LocLabelL.y = ptOnLineL.y + Constants.locLabelLY; // LocEqL.x = ptOnLineE.x + Constants.locEqX; // LocEqL.y = ptOnLineE.y + Constants.locEqY; */ }// end InitLocLabelP //******************************* // // Draw // // Draw a point // //****************************** public void Draw(Graphics g, FramePoint bf) { if (appearanceP.visible == StateVisible.visible) { if (appearanceP.fill == StateFill.fill) { g.setColor(appearanceP.fillcolor); fillShape(g); } g.setColor(Constants.contcolor); // set to default if (appearanceP.contour == StateContour.contour) { g.setColor(appearanceP.contcolor); drawShape(g); } g.setColor(Color.black);// may want to control color of label - later if (bf.state.stateLabel == StateLabel.insert) DrawLabelInsert(g); if (bf.state.stateLabel == StateLabel.xcoord) DrawLabelXCoord(g); if (bf.state.stateLabel == StateLabel.user) DrawLabelUser(g); }// end if visible if (selected == StateSelect.yes) { DrawSelect(g, bf); } DrawCoord(g,bf); }// end Draw //******************************* // // DrawSelect // // Draw a selected point // //****************************** public void DrawSelect(Graphics g, FramePoint bf) { g.setColor(Constants.selectC); switch (appearanceP.shape) { case StateShape.scircle: //The integers 1, 5 etc. are subtracted to adjust //the position of the points for different shapes. g.fillOval(x-2, y-2, 6, 6); break; case StateShape.lcircle: g.fillOval(x-5, y-5, 12, 12); break; case StateShape.square: g.fillRect(x-5, y-5, 12, 12); break; }//end of switch shape }// end DrawSelect //******************************* // // DrawCoord // // Draw coordinates of a point // //****************************** public void DrawCoord(Graphics g, FramePoint bf) { g.setColor(Constants.colorCoord); if (appearanceP.wCoord == StateCoord.absolute) { g.drawString("(" + x + "," + y + ")", x+LocCoordP.x, y+LocCoordP.y); } else if (appearanceP.wCoord == StateCoord.relative) { g.drawString("(" + rx.n + "/" + rx.d + "," + ry.n + "/" + ry.d + ")", x+LocCoordP.x, y+LocCoordP.y); }; }// end DrawCoord //******************************* // // DrawEq // // Draw equation of a line // //****************************** public void DrawEq(Graphics g) { System.out.println("LocEqL.x = " + LocEqL.x + ", LocEqL.y = " + LocEqL.y); g.drawString("" + linsert, LocEqL.x, LocEqL.y); }// end DrawEq //******************************* // // DrawLineLabel // // Draw label of a line // //****************************** public void DrawLineLabel(Graphics g) { //System.out.println("LocLabelL.x = " + LocLabelL.x + ", LocLabelL.y = " + //LocLabelL.y); g.drawString("" + linsert, LocLabelL.x, LocLabelL.y); g.drawString("" + linsert, LocEqL.x, LocEqL.y); }// end DrawLabel //******************************* // // Helping functions for Draw: // // drawShape // fillShape // //****************************** void drawShape (Graphics g) { switch (appearanceP.shape) { case StateShape.scircle: //The integers 1, 5 etc. are subtracted to adjust //the position of the points for different shapes. g.drawOval(x-2, y-2, 4, 4); break; case StateShape.lcircle: g.drawOval(x-5, y-5, 10, 10); break; case StateShape.square: g.drawRect(x-5, y-5, 10, 10); break; }//end of switch shape } //ends drawShape //************************** // FillShape //************************** void fillShape (Graphics g) { switch (appearanceP.shape) { case StateShape.scircle: //The integers 1, 5 etc. are subtracted to adjust //the position of the points for different shapes. g.fillOval(x-2, y-2, 4, 4); break; case StateShape.lcircle: g.fillOval(x-5, y-5, 10, 10); break; case StateShape.square: g.fillRect(x-5, y-5, 10, 10); break; }//end of switch shape } //ends drawShape //******************************* // // DrawLabelInsert // //****************************** public void DrawLabelInsert(Graphics g) { g.drawString(""+linsert, x+LocLabelP.x, y+LocLabelP.y); } //******************************* // // DrawLabelXCoord // //****************************** public void DrawLabelXCoord(Graphics g) { g.drawString(""+lxcoord, x+LocLabelP.x, y+LocLabelP.y); } //******************************* // // DrawLabelUser // //****************************** public void DrawLabelUser(Graphics g) { g.drawString(appearanceP.userLabel, x+LocLabelP.x, y+LocLabelP.y); } //******************************* // // DrawLine // //******************************* public void DrawLine(Graphics g, int width, int height, Point or, boolean wOrient, Rational unitL, int duality) { g.setColor(appearanceL.color); if (appearanceL.style == StateStyle.solid) g.drawLine(hookN.x,hookN.y,hookS.x,hookS.y); if (appearanceL.style == StateStyle.dotted) DrawDottedLine(hookN.x,hookN.y,hookS.x,hookS.y,g); if (appearanceL.thickness == StateThickness.thick1) DrawThickLine(hookN.x, hookN.y, hookS.x, hookS.y, 1, appearanceL.style,g); if (appearanceL.thickness == StateThickness.thick2) DrawThickLine(hookN.x, hookN.y, hookS.x, hookS.y, 2, appearanceL.style,g); if (appearanceL.thickness == StateThickness.thick3) DrawThickLine(hookN.x, hookN.y, hookS.x, hookS.y, 3, appearanceL.style,g); // draw selected lines if (selected == StateSelect.yes) { g.setColor(Constants.selectC); if (appearanceL.thickness == StateThickness.thick1) DrawThickLine(hookN.x, hookN.y, hookS.x, hookS.y, 1, appearanceL.style,g); if (appearanceL.thickness == StateThickness.thick2) DrawThickLine(hookN.x, hookN.y, hookS.x, hookS.y, 2, appearanceL.style,g); if (appearanceL.thickness == StateThickness.thick3) DrawThickLine(hookN.x, hookN.y, hookS.x, hookS.y, 3, appearanceL.style,g); } // draw line label DrawLineLabel(g); // draw line equation DrawEq(g); }// end DrawLine //******************************************** // // ComputeLineHooks // for line drawing // //********************************************* public void ComputeLineHooks(int width, int height, Point or, boolean wOrient, Rational unitL, int duality, Point hookS, Point hookN) { // compute two points on the line // idea: to use these precomputed points for drawing the line, and // for the line label and location of equation on the screen //The following calculation aims at getting two points on any //side of the window, eg: // ---------.--- // | | // | | // | | // . | // | | // | . // | | // ---------.--- // Ileana's version, first with integers, later - maybe - with more precision int sig = 1; if (wOrient == false) sig = -1; // compute relative values of N, S, E, W points // i.e. intersection of axes with the canvas Rational Nx = new Rational(0, 1); Rational Ny = new Rational(or.y*sig,1); Ny = Ny.DivR(unitL); Rational Sx = new Rational(0,1); Rational Sy = new Rational((height - or.y)*(-sig), 1); Sy = Sy.DivR(unitL); Rational PNx = new Rational(0, 1); Rational PNy = new Rational(0,1); Rational PSx = new Rational(0,1); Rational PSy = new Rational(0, 1); if (duality == StateDuality.dual1) { // to fix for y=2ax-b PNy.n = Ny.n; PNy.d = Ny.d; PNx = PNy.AddR(ry).DivR(rx); PNx.d = 2*PNx.d; // the "2" in the duality PSy.n = Sy.n; PSy.d = Sy.d; PSx = PSy.AddR(ry).DivR(rx); PSx.d = 2*PSx.d; // the "2" in the duality }// end dual1 /* else if (duality == StateDuality.dual2) { // this should be OK, but check PNy = Ny; PNx = PNy.AddR(ry).DivR(rx); PSy = Sy; PSx = PSy.AddR(ry).DivR(rx); PWx = Wx; PWy = rx.MulR(PWx).SubR(ry); PEx = Ex; PEy = rx.MulR(PEx).SubR(ry); }// end dual2 else if (duality == StateDuality.dual3) { // to fix for ax+by=1 PNy = Ny; PNx = PNy.AddR(ry).DivR(rx); PSy = Sy; PSx = PSy.AddR(ry).DivR(rx); PWx = Wx; PWy = rx.MulR(PWx).SubR(ry); PEx = Ex; PEy = rx.MulR(PEx).SubR(ry); }// end dual3 else // if (duality == StateDuality.dual4) { // to fix for ax+by+1=0 PNy = Ny; PNx = PNy.AddR(ry).DivR(rx); PSy = Sy; PSx = PSy.AddR(ry).DivR(rx); PWx = Wx; PWy = rx.MulR(PWx).SubR(ry); PEx = Ex; PEy = rx.MulR(PEx).SubR(ry); }// end dual4 */ // convert to absolute values int pnx=0, pny=0, psx=0, psy=0; if(PNx != Constants.Infinity) pnx = PNx.RelToAbs(or.x, unitL, 1); else System.out.println("PNx is Infinity"); // ??? to fix if(PNy != Constants.Infinity) pny = PNy.RelToAbs(or.y, unitL, sig); else System.out.println("PNy is Infinity"); if(PSx != Constants.Infinity) psx = PSx.RelToAbs(or.x, unitL, 1); else System.out.println("PSx is Infinity"); if(PSy != Constants.Infinity) psy = PSy.RelToAbs(or.y, unitL, sig); else System.out.println("PSy is Infinity"); hookN.x = pnx; hookN.y = pny + 20; hookS.x = psx; hookS.y = psy - 20; }// end ComputeLineHooks //******************************* // DrawDottedLine // draws dotted line // //******************************* public void DrawDottedLine (int x1, int y1, int x2, int y2, Graphics g) { /* int lseg = Constants.dotSize; float changeX ; float changeY; int div; int diffx; float ct1; // compute diffx and diffy and ct1 (gradient) // compute changeX, changeY using formula, and ct1 and ct2 // compute div using div = diffx/changeX + 1; // then draw if (x1 > x2) diffx = x1-x2; else diffx = x2-x1; div = diffx/changeX + 1; .... // compute part if (x1 > x2) { if (y1 > y2) { for (int i = 0; i < div; i = i+2) g.drawLine ((int)(x2+(changeX*i)), (int)(y2+(changeY*i)), (int)(x2+(changeX*(i+1))), (int)(y2+(changeY*(i+1)))); } else if (y1 < y2) { for (int i = 0; i < div; i = i+2) g.drawLine ((int)(x2+(changeX*i)), (int)(y2-(changeY*i)), (int)(x2+(changeX*(i+1))), (int)(y2-(changeY*(i+1)))); } else { for (int i = 0; i < div; i = i+2) g.drawLine ((int)(x2+(changeX*i)), y1, (int)(x2+(changeX*(i+1))), y1); } } else if (x1 < x2) { if (y1 > y2) { for (int i = 0; i < div; i = i+2) g.drawLine ((int)(x1+(changeX*i)), (int)(y1-(changeY*i)), (int)(x1+(changeX*(i+1))), (int)(y1-(changeY*(i+1)))); } else if (y1 < y2) { for (int i = 0; i < div; i = i+2) g.drawLine ((int)(x1+(changeX*i)), (int)(y1+(changeY*i)), (int)(x1+(changeX*(i+1))), (int)(y1+(changeY*(i+1)))); } else { for (int i = 0; i < div; i = i+2) g.drawLine ((int)(x1+(changeX*i)), y1, (int)(x1+(changeX*(i+1))),y1); } } else { if (y1 > y2) { for (int i = 0; i < div; i = i+2) g.drawLine (x1, (int)(y1-(changeY*i)), x1, (int)(y1-(changeY*(i+1)))); } else if (y1 < y2) { for (int i = 0; i < div; i = i+2) g.drawLine (x1, (int)(y1+(changeY*i)), x1, (int)(y1+(changeY*(i+1)))); } } */ }// end DrawDotted Line //***************************************************** // // DrawThickLine // draw a line of given thickness, non-horizonthal // adjusted horizontally, left to right // //******************************************************* public void DrawThickLine(int x1, int y1, int x2, int y2, int thick, int style, Graphics g) { if (style == StateStyle.solid) g.drawLine(x1,y1,x2,y2); if (style == StateStyle.dotted) DrawDottedLine(x1,y1,x2,y2,g); // g.drawLine(x1, y1, x2, y2); for (int i = 1; i < thick/2 + 1; i++) { //g.drawLine(x1-i, y1, x2-i, y2); if (style == StateStyle.solid) g.drawLine(x1-i,y1,x2-i,y2); if (style == StateStyle.dotted) DrawDottedLine(x1-i,y1,x2-i,y2,g); } for (int i = 1; i < (thick+1)/2 ; i++) { // g.drawLine(x1+i, y1, x2+i, y2); if (style == StateStyle.solid) g.drawLine(x1+i,y1,x2+i,y2); if (style == StateStyle.dotted) DrawDottedLine(x1+i,y1,x2+i,y2,g); } }// end DrawThickLine //***************************************************** // // DrawThickHorizLine // draw a line of given thickness, horizonthal // //******************************************************* public void DrawThickHorizLine(int x1, int y1, int x2, int thick, int style, Graphics g) { // g.drawLine(x1, y1, x2, y1); if (style == StateStyle.solid) g.drawLine(x1,y1,x2,y1); if (style == StateStyle.dotted) DrawDottedLine(x1,y1,x2,y1,g); for (int i = 1; i < thick/2 + 1; i++) { //g.drawLine(x1, y1-i, x2, y1-i); if (style == StateStyle.solid) g.drawLine(x1,y1-i,x2,y1-i); if (style == StateStyle.dotted) DrawDottedLine(x1,y1-i,x2,y1-i,g); } for (int i = 1; i < (thick+1)/2 ; i++) { //g.drawLine(x1, y1+i, x2, y1+i); if (style == StateStyle.solid) g.drawLine(x1,y1+i,x2,y1+i); if (style == StateStyle.dotted) DrawDottedLine(x1,y1+i,x2,y1+i,g); } }// end DrawThickHorizLine }//end class PointObj