/**
* ORIPA - Origami Pattern Editor
* Copyright (C) 2005-2009 Jun Mitani http://mitani.cs.tsukuba.ac.jp/
This program 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 3 of the License, or
(at your option) any later version.
This program 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 oripa;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.vecmath.Vector2d;
import oripa.geom.*;
public class RenderScreenForCheck extends JPanel
implements MouseListener, MouseMotionListener, MouseWheelListener, ActionListener, ComponentListener {
private boolean bDrawFaceID = false;
private Image bufferImage;
private Graphics2D bufferg;
private Point2D preMousePoint; // Screen coordinates
private Point2D currentMouseDraggingPoint = null;
private Point2D.Double currentMousePointLogic = new Point2D.Double(); // Logical coordinates
private double scale;
private double transX;
private double transY;
// Temporary information when editing
private OriLine prePickLine = null;
private Vector2d prePickV = null;
private Vector2d preprePickV = null;
private Vector2d prepreprePickV = null;
private Vector2d pickCandidateV = null;
private OriLine pickCandidateL = null;
private ArrayList<Vector2d> tmpOutline = new ArrayList<>(); // Contour line in the edit
private boolean dispGrid = true;
// Affine transformation information
private Dimension preSize;
private AffineTransform affineTransform = new AffineTransform();
private ArrayList<Vector2d> crossPoints = new ArrayList<>();
private JPopupMenu popup = new JPopupMenu();
private JMenuItem popupItem_DivideFace = new JMenuItem("Face division");
private JMenuItem popupItem_FlipFace = new JMenuItem("Face Inversion");
RenderScreenForCheck() {
addMouseListener(this);
addMouseMotionListener(this);
addMouseWheelListener(this);
addComponentListener(this);
scale = 1.5;
setBackground(Color.white);
popupItem_DivideFace.addActionListener(this);
popup.add(popupItem_DivideFace);
popupItem_FlipFace.addActionListener(this);
popup.add(popupItem_FlipFace);
preSize = getSize();
}
public void drawModel(Graphics2D g2d) {
for (OriFace face : ORIPA.doc.faces) {
g2d.setColor(new Color(255, 210, 210));
g2d.fill(face.preOutline);
}
g2d.setColor(Color.RED);
for (OriVertex v : ORIPA.doc.vertices) {
if (v.hasProblem) {
g2d.fill(new Rectangle2D.Double(v.preP.x - 8.0 / scale,
v.preP.y - 8.0 / scale, 16.0 / scale, 16.0 / scale));
}
}
if (bDrawFaceID) {
g2d.setColor(Color.BLACK);
for (OriFace face : ORIPA.doc.faces) {
g2d.drawString("" + face.tmpInt, (int) face.getCenter().x, (int) face.getCenter().y);
}
}
if (Config.FOR_STUDY) {
g2d.setColor(new Color(255, 210, 220));
for (OriFace face : ORIPA.doc.faces) {
if (face.tmpInt2 == 0) {
g2d.setColor(Color.RED);
g2d.fill(face.preOutline);
} else {
g2d.setColor(face.color);
}
if (face.hasProblem) {
g2d.setColor(Color.RED);
} else {
if (face.faceFront) {
g2d.setColor(new Color(255, 200, 200));
} else {
g2d.setColor(new Color(200, 200, 255));
}
}
g2d.fill(face.preOutline);
}
g2d.setColor(Color.BLACK);
for (OriFace face : ORIPA.doc.faces) {
g2d.drawString("" + face.z_order, (int) face.getCenter().x,
(int) face.getCenter().y);
}
g2d.setColor(Color.RED);
for (OriVertex v : ORIPA.doc.vertices) {
if (v.hasProblem) {
g2d.fill(new Rectangle2D.Double(v.p.x - 8.0 / scale,
v.p.y - 8.0 / scale, 16.0 / scale, 16.0 / scale));
}
}
}
}
// To update the current AffineTransform
private void updateAffineTransform() {
affineTransform.setToIdentity();
affineTransform.translate(getWidth() * 0.5, getHeight() * 0.5);
affineTransform.scale(scale, scale);
affineTransform.translate(transX, transY);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (bufferImage == null) {
bufferImage = createImage(getWidth(), getHeight());
bufferg = (Graphics2D) bufferImage.getGraphics();
updateAffineTransform();
preSize = getSize();
}
bufferg.setTransform(new AffineTransform());
bufferg.setColor(Color.WHITE);
bufferg.fillRect(0, 0, getWidth(), getHeight());
bufferg.setTransform(affineTransform);
Graphics2D g2d = bufferg;
g2d.setStroke(Config.STROKE_VALLEY);
g2d.setColor(Color.black);
for (OriLine line : ORIPA.doc.lines) {
switch (line.type) {
case OriLine.TYPE_NONE:
if (!Globals.dispAuxLines) {
continue;
}
g2d.setColor(Config.LINE_COLOR_AUX);
g2d.setStroke(Config.STROKE_CUT);
break;
case OriLine.TYPE_CUT:
g2d.setColor(Color.BLACK);
g2d.setStroke(Config.STROKE_CUT);
break;
case OriLine.TYPE_RIDGE:
if (!Globals.dispMVLines) {
continue;
}
g2d.setColor(Config.LINE_COLOR_RIDGE);
g2d.setStroke(Config.STROKE_RIDGE);
break;
case OriLine.TYPE_VALLEY:
if (!Globals.dispMVLines) {
continue;
}
g2d.setColor(Config.LINE_COLOR_VALLEY);
g2d.setStroke(Config.STROKE_VALLEY);
break;
}
if ((Globals.editMode == Constants.EditMode.INPUT_LINE
&& Globals.lineInputMode == Constants.LineInputMode.MIRROR
&& line.selected)
|| (Globals.editMode == Constants.EditMode.PICK_LINE
&& line.selected)) {
g2d.setColor(Color.RED);
g2d.setStroke(Config.STROKE_PICKED);
}
if (line == prePickLine) {
g2d.setColor(Color.RED);
g2d.setStroke(Config.STROKE_PICKED);
} else if (line == pickCandidateL) {
g2d.setColor(Config.LINE_COLOR_CANDIDATE);
g2d.setStroke(Config.STROKE_PICKED);
}
g2d.draw(new Line2D.Double(line.p0.x, line.p0.y, line.p1.x, line.p1.y));
}
// Drawing of the vertices
for (OriVertex v : ORIPA.doc.vertices) {
double vertexDrawSize = 2.0;
g2d.setColor(Color.BLACK);
if (v.hasProblem) {
vertexDrawSize = 5.0;
g2d.setColor(Color.RED);
}
g2d.fill(new Rectangle2D.Double(v.preP.x - vertexDrawSize / scale, v.preP.y - vertexDrawSize / scale, vertexDrawSize * 2 / scale, vertexDrawSize * 2 / scale));
}
for (Vector2d v : crossPoints) {
g2d.setColor(Color.RED);
g2d.fill(new Rectangle2D.Double(v.x - 5.0 / scale, v.y - 5.0 / scale, 10.0 / scale, 10.0 / scale));
}
// Line connecting the pair of unsetled faces
if (Config.FOR_STUDY) {
if (ORIPA.doc.overlapRelation != null) {
g2d.setStroke(Config.STROKE_RIDGE);
g2d.setColor(Color.MAGENTA);
int size = ORIPA.doc.faces.size();
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
if (ORIPA.doc.overlapRelation[i][j] == Doc.UNDEFINED) {
Vector2d v0 = ORIPA.doc.faces.get(i).getCenter();
Vector2d v1 = ORIPA.doc.faces.get(j).getCenter();
g2d.draw(new Line2D.Double(v0.x, v0.y, v1.x, v1.y));
}
}
}
}
}
drawModel(g2d);
g.drawImage(bufferImage, 0, 0, this);
}
public void setDispGrid(boolean dispGrid) {
this.dispGrid = dispGrid;
resetPickElements();
repaint();
}
// 0: OriLine
// 1: The nearest point Vector
private boolean pickPointOnLine(Point2D.Double p, Object[] line_vertex) {
double minDistance = Double.MAX_VALUE;
OriLine bestLine = null;
Vector2d nearestPoint = new Vector2d();
Vector2d tmpNearestPoint = new Vector2d();
for (OriLine line : ORIPA.doc.lines) {
double dist = GeomUtil.DistancePointToSegment(new Vector2d(p.x, p.y), line.p0, line.p1, tmpNearestPoint);
if (dist < minDistance) {
minDistance = dist;
bestLine = line;
nearestPoint.set(tmpNearestPoint);
}
}
if (minDistance / scale < 5) {
line_vertex[0] = bestLine;
line_vertex[1] = nearestPoint;
return true;
} else {
return false;
}
}
private Vector2d pickVertex(Point2D.Double p) {
double minDistance = Double.MAX_VALUE;
Vector2d minPosition = new Vector2d();
for (OriLine line : ORIPA.doc.lines) {
double dist0 = p.distance(line.p0.x, line.p0.y);
if (dist0 < minDistance) {
minDistance = dist0;
minPosition.set(line.p0);
}
double dist1 = p.distance(line.p1.x, line.p1.y);
if (dist1 < minDistance) {
minDistance = dist1;
minPosition.set(line.p1);
}
}
if (dispGrid) {
double step = ORIPA.doc.size / Globals.gridDivNum;
for (int ix = 0; ix < Globals.gridDivNum + 1; ix++) {
for (int iy = 0; iy < Globals.gridDivNum + 1; iy++) {
double x = -ORIPA.doc.size / 2 + step * ix;
double y = -ORIPA.doc.size / 2 + step * iy;
double dist = p.distance(x, y);
if (dist < minDistance) {
minDistance = dist;
minPosition.set(x, y);
}
}
}
}
if (minDistance < 10.0 / scale) {
return minPosition;
} else {
return null;
}
}
public void modeChanged() {
resetPickElements();
repaint();
}
public void resetPickElements() {
prePickV = null;
prePickLine = null;
pickCandidateV = null;
preprePickV = null;
prepreprePickV = null;
crossPoints.clear();
tmpOutline.clear();
}
private OriLine pickLine(Point2D.Double p) {
double minDistance = Double.MAX_VALUE;
OriLine bestLine = null;
for (OriLine line : ORIPA.doc.lines) {
if (Globals.editMode == Constants.EditMode.DELETE_LINE) {
}
double dist = GeomUtil.DistancePointToSegment(new Vector2d(p.x, p.y), line.p0, line.p1);
if (dist < minDistance) {
minDistance = dist;
bestLine = line;
}
}
if (minDistance / scale < 10) {
return bestLine;
} else {
return null;
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (javax.swing.SwingUtilities.isRightMouseButton(e)) {
if (prepreprePickV != null) {
prepreprePickV = null;
repaint();
} else if (preprePickV != null) {
preprePickV = null;
repaint();
} else if (prePickV != null) {
prePickV = null;
repaint();
} else if (!tmpOutline.isEmpty()) {
tmpOutline.remove(tmpOutline.size() - 1);
repaint();
}
if (Globals.editMode == Constants.EditMode.INPUT_LINE
&& Globals.lineInputMode == Constants.LineInputMode.COPY_AND_PASTE) {
Globals.lineInputMode = Constants.LineInputMode.DIRECT_V;
ORIPA.mainFrame.uiPanel.modeChanged();
ORIPA.doc.tmpSelectedLines.clear();
repaint();
}
return;
}
if (Globals.editMode == Constants.EditMode.NONE) {
return;
}
// Gets the logical coordinates of the click
Point2D.Double clickPoint = new Point2D.Double();
try {
affineTransform.inverseTransform(e.getPoint(), clickPoint);
} catch (Exception ex) {
return;
}
if (Globals.editMode == Constants.EditMode.CHANGE_LINE_TYPE) {
OriLine l = pickLine(clickPoint);
if (l != null) {
ORIPA.doc.pushUndoInfo();
if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK) {
// When you press the Ctrl: outline
l.type = OriLine.TYPE_CUT;
} else {
l.changeToNextType();
}
}
repaint();
return;
} else if (Globals.editMode == Constants.EditMode.DELETE_LINE) {
OriLine l = pickLine(clickPoint);
if (l != null) {
ORIPA.doc.pushUndoInfo();
ORIPA.doc.removeLine(l);
}
repaint();
return;
} else if (Globals.editMode == Constants.EditMode.PICK_LINE) {
OriLine l = pickLine(clickPoint);
if (l != null) {
// skip if ocult
if (!Globals.dispMVLines && (l.type == OriLine.TYPE_RIDGE || l.type == OriLine.TYPE_VALLEY)) {
return;
}
if (!Globals.dispAuxLines && l.type == OriLine.TYPE_NONE) {
return;
}
l.selected = !l.selected;
}
repaint();
return;
} else if (Globals.editMode == Constants.EditMode.ADD_VERTEX) {
Object[] line_vertex = new Object[2];
if (pickPointOnLine(currentMousePointLogic, line_vertex)) {
ORIPA.doc.pushUndoInfo();
if (!ORIPA.doc.addVertexOnLine((OriLine) line_vertex[0], (Vector2d) line_vertex[1])) {
ORIPA.doc.popUndoInfo();
}
this.pickCandidateV = null;
repaint();
}
return;
} else if (Globals.editMode == Constants.EditMode.DELETE_VERTEX) {
Vector2d v = pickVertex(clickPoint);
if (v != null) {
ORIPA.doc.pushUndoInfo();
ORIPA.doc.removeVertex(v);
repaint();
}
return;
} else if (Globals.editMode == Constants.EditMode.EDIT_OUTLINE) {
Vector2d v = pickVertex(currentMousePointLogic);
// Add the outline being edited
if (v != null) {
// Closes if match existing point
boolean bClose = false;
for (Vector2d tv : tmpOutline) {
if (GeomUtil.Distance(v, tv) < 1) {
bClose = true;
break;
}
}
if (bClose) {
if (tmpOutline.size() > 2) {
closeTmpOutline();
}
} else {
tmpOutline.add(v);
}
repaint();
}
return;
} else if (Globals.editMode == Constants.EditMode.INPUT_LINE) {
if (Globals.lineInputMode == Constants.LineInputMode.DIRECT_V) {
Vector2d v = pickVertex(clickPoint);
if (v == null) {
if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK) {
OriLine l = pickLine(clickPoint);
if (l != null) {
v = new Vector2d();
Vector2d cp = new Vector2d(clickPoint.x, clickPoint.y);
GeomUtil.DistancePointToSegment(cp, l.p0, l.p1, v);
}
}
}
if (v != null) {
if (prePickV == null) {
prePickV = v;
} else {
OriLine line = new OriLine(prePickV, v, Globals.inputLineType);
ORIPA.doc.pushUndoInfo();
ORIPA.doc.addLine(line);
prePickV = null;
}
}
} else if (Globals.lineInputMode == Constants.LineInputMode.PBISECTOR) {
Vector2d v = pickVertex(clickPoint);
if (v != null) {
if (prePickV == null) {
prePickV = v;
} else {
ORIPA.doc.pushUndoInfo();
ORIPA.doc.addPBisector(prePickV, v);
prePickV = null;
}
}
} else if (Globals.lineInputMode == Constants.LineInputMode.COPY_AND_PASTE) {
Vector2d v = pickVertex(clickPoint);
if (v != null) {
if (!ORIPA.doc.tmpSelectedLines.isEmpty()) {
ORIPA.doc.pushUndoInfo();
double ox = ORIPA.doc.tmpSelectedLines.get(0).p0.x;
double oy = ORIPA.doc.tmpSelectedLines.get(0).p0.y;
for (OriLine l : ORIPA.doc.tmpSelectedLines) {
double mx = v.x;
double my = v.y;
double sx = mx + l.p0.x - ox;
double sy = my + l.p0.y - oy;
double ex = mx + l.p1.x - ox;
double ey = my + l.p1.y - oy;
OriLine line = new OriLine(sx, sy, ex, ey, l.type);
ORIPA.doc.addLine(line);
}
}
}
} else if (Globals.lineInputMode == Constants.LineInputMode.ON_V) {
Vector2d v = pickVertex(clickPoint);
if (v == null) {
if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK) {
OriLine l = pickLine(clickPoint);
if (l != null) {
v = new Vector2d();
Vector2d cp = new Vector2d(clickPoint.x, clickPoint.y);
GeomUtil.DistancePointToSegment(cp, l.p0, l.p1, v);
}
}
}
if (v != null) {
if (prePickV == null) {
prePickV = v;
} else {
Vector2d dir = new Vector2d(v.x - prePickV.x, v.y - prePickV.y);
dir.normalize();
dir.scale(Constants.DEFAULT_PAPER_SIZE * 8);
OriLine line = new OriLine(prePickV.x - dir.x, prePickV.y - dir.y, prePickV.x + dir.x, prePickV.y + dir.y, Globals.inputLineType);
if (GeomUtil.clipLine(line, ORIPA.doc.size / 2)) {
ORIPA.doc.pushUndoInfo();
ORIPA.doc.addLine(line);
}
prePickV = null;
}
}
} else if (Globals.lineInputMode == Constants.LineInputMode.SYMMETRIC_LINE) {
Vector2d v = pickVertex(clickPoint);
if (v != null) {
if (preprePickV == null) {
preprePickV = v;
} else if (prePickV == null) {
prePickV = v;
} else {
ORIPA.doc.pushUndoInfo();
if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK) {
ORIPA.doc.addSymmetricLineAutoWalk(preprePickV, prePickV, v, 0, preprePickV);
} else {
ORIPA.doc.addSymmetricLine(preprePickV, prePickV, v);
}
prePickV = null;
preprePickV = null;
}
}
} else if (Globals.lineInputMode == Constants.LineInputMode.TRIANGLE_SPLIT) {
Vector2d v = pickVertex(clickPoint);
if (v != null) {
if (preprePickV == null) {
preprePickV = v;
} else if (prePickV == null) {
prePickV = v;
} else {
ORIPA.doc.pushUndoInfo();
ORIPA.doc.addTriangleDivideLines(v, prePickV, preprePickV);
prePickV = null;
preprePickV = null;
}
}
} else if (Globals.lineInputMode == Constants.LineInputMode.BISECTOR) {
if (prepreprePickV == null) {
prepreprePickV = pickVertex(clickPoint);
if (prepreprePickV != null) {
pickCandidateV = null;
}
} else if (preprePickV == null) {
preprePickV = pickVertex(clickPoint);
} else if (prePickV == null) {
prePickV = pickVertex(clickPoint);
} else {
OriLine l = pickLine(clickPoint);
if (l != null) {
ORIPA.doc.pushUndoInfo();
ORIPA.doc.addBisectorLine(prepreprePickV, preprePickV, prePickV, l);
prePickV = null;
preprePickV = null;
prepreprePickV = null;
}
}
} else if (Globals.lineInputMode == Constants.LineInputMode.VERTICAL_LINE) {
if (prePickV == null) {
prePickV = pickVertex(clickPoint);
if (prePickV != null) {
pickCandidateV = null;
}
pickCandidateV = null;
} else {
OriLine l = pickLine(clickPoint);
if (l != null) {
OriLine vl = GeomUtil.getVerticalLine(prePickV, l, Globals.inputLineType);
ORIPA.doc.pushUndoInfo();
ORIPA.doc.addLine(vl);
prePickV = null;
}
}
} else if (Globals.lineInputMode == Constants.LineInputMode.MIRROR) {
OriLine l = pickLine(clickPoint);
if (l != null) {
if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK) {
ORIPA.doc.mirrorCopyBy(l);
ORIPA.doc.resetSelectedOriLines();
ORIPA.doc.pushUndoInfo();
} else {
l.selected = !l.selected;
}
}
repaint();
return;
} else if (Globals.lineInputMode == Constants.LineInputMode.BY_VALUE) {
if (Globals.subLineInputMode == Constants.SubLineInputMode.NONE) {
Vector2d v = pickVertex(clickPoint);
if (v != null) {
double length;
double angle;
try {
length = Double.valueOf(ORIPA.mainFrame.uiPanel.textFieldLength.getText());
angle = Double.valueOf(ORIPA.mainFrame.uiPanel.textFieldAngle.getText());
if (length > 0) {
OriLine vl = GeomUtil.getLineByValue(v, length,
-angle, Globals.inputLineType);
ORIPA.doc.pushUndoInfo();
ORIPA.doc.addLine(vl);
}
} catch (Exception ex) {
}
}
} else if (Globals.subLineInputMode == Constants.SubLineInputMode.PICK_LENGTH) {
Vector2d v = pickVertex(clickPoint);
if (v != null) {
if (prePickV == null) {
prePickV = v;
} else {
double length = GeomUtil.Distance(prePickV, v);
ORIPA.mainFrame.uiPanel.textFieldLength.setValue(new Double(length));
Globals.subLineInputMode = Constants.SubLineInputMode.NONE;
ORIPA.mainFrame.uiPanel.modeChanged();
}
}
} else if (Globals.subLineInputMode == Constants.SubLineInputMode.PICK_ANGLE) {
Vector2d v = pickVertex(clickPoint);
if (v != null) {
if (preprePickV == null) {
preprePickV = v;
} else if (prePickV == null) {
prePickV = v;
} else {
Vector2d dir1 = new Vector2d(v);
Vector2d dir2 = new Vector2d(preprePickV);
dir1.sub(prePickV);
dir2.sub(prePickV);
double deg_angle = Math.toDegrees(dir1.angle(dir2));
ORIPA.mainFrame.uiPanel.textFieldAngle.setValue(new Double(deg_angle));
Globals.subLineInputMode = Constants.SubLineInputMode.NONE;
ORIPA.mainFrame.uiPanel.modeChanged();
}
}
}
}
}
repaint();
}
private Vector2d isOnTmpOutlineLoop(Vector2d v) {
for (int i = 0; i < tmpOutline.size(); i++) {
Vector2d p0 = tmpOutline.get(i);
Vector2d p1 = tmpOutline.get((i + 1) % tmpOutline.size());
if (GeomUtil.DistancePointToLine(v, new Line(p0, new Vector2d(p1.x - p0.x, p1.y - p0.y))) < ORIPA.doc.size * 0.001) {
return p0;
}
}
return null;
}
private boolean isOutsideOfTmpOutlineLoop(Vector2d v) {
Vector2d p0 = tmpOutline.get(0);
Vector2d p1 = tmpOutline.get(1);
boolean CCWFlg = GeomUtil.CCWcheck(p0, p1, v);
for (int i = 1; i < tmpOutline.size(); i++) {
p0 = tmpOutline.get(i);
p1 = tmpOutline.get((i + 1) % tmpOutline.size());
if (CCWFlg != GeomUtil.CCWcheck(p0, p1, v)) {
return true;
}
}
return false;
}
private void closeTmpOutline() {
ORIPA.doc.pushUndoInfo();
// Delete the current outline
ArrayList<OriLine> outlines = new ArrayList<>();
for (OriLine line : ORIPA.doc.lines) {
if (line.type == OriLine.TYPE_CUT) {
outlines.add(line);
}
}
for (OriLine line : outlines) {
ORIPA.doc.lines.remove(line);
}
// Update the contour line
int outlineVnum = tmpOutline.size();
for (int i = 0; i < outlineVnum; i++) {
OriLine line = new OriLine(tmpOutline.get(i),
tmpOutline.get((i + 1) % outlineVnum), OriLine.TYPE_CUT);
ORIPA.doc.addLine(line);
}
// To delete a segment of the outer contour
while (true) {
boolean bDeleteLine = false;
for (OriLine line : ORIPA.doc.lines) {
if (line.type == OriLine.TYPE_CUT) {
continue;
}
Vector2d OnPoint0 = isOnTmpOutlineLoop(line.p0);
Vector2d OnPoint1 = isOnTmpOutlineLoop(line.p1);
// Delete(if you're overlap with contour lines
if (OnPoint0 != null && OnPoint0 == OnPoint1) {
ORIPA.doc.removeLine(line);
bDeleteLine = true;
break;
}
// Also delete if one point is out
if ((OnPoint0 == null && isOutsideOfTmpOutlineLoop(line.p0))
|| (OnPoint1 == null && isOutsideOfTmpOutlineLoop(line.p1))) {
ORIPA.doc.removeLine(line);
bDeleteLine = true;
break;
}
}
if (!bDeleteLine) {
break;
}
}
tmpOutline.clear();
Globals.editMode = Globals.preEditMode;
ORIPA.mainFrame.uiPanel.modeChanged();
}
@Override
public void mousePressed(MouseEvent e) {
preMousePoint = e.getPoint();
}
@Override
public void mouseReleased(MouseEvent arg0) {
// Retangular selection
if (Globals.editMode == Constants.EditMode.PICK_LINE) {
Point2D.Double sp = new Point2D.Double();
Point2D.Double ep = new Point2D.Double();
try {
affineTransform.inverseTransform(preMousePoint, sp);
affineTransform.inverseTransform(currentMouseDraggingPoint, ep);
RectangleClipper clipper = new RectangleClipper(Math.min(sp.x, ep.x),
Math.min(sp.y, ep.y),
Math.max(sp.x, ep.x),
Math.max(sp.y, ep.y));
for (OriLine l : ORIPA.doc.lines) {
if (l.type == OriLine.TYPE_CUT) {
continue;
}
// skip if ocult
if (!Globals.dispMVLines && (l.type == OriLine.TYPE_RIDGE ||
l.type == OriLine.TYPE_VALLEY)) {
continue;
}
if (!Globals.dispAuxLines && l.type == OriLine.TYPE_NONE) {
continue;
}
if (clipper.clipTest(l)) {
l.selected = true;
}
}
} catch (Exception ex) {
}
}
currentMouseDraggingPoint = null;
repaint();
}
@Override
public void mouseEntered(MouseEvent arg0) {
}
@Override
public void mouseExited(MouseEvent arg0) {
}
@Override
public void mouseDragged(MouseEvent e) {
if ((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0 && // zoom
(e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK) {
double moved = e.getX() - preMousePoint.getX() + e.getY() - preMousePoint.getY();
scale += moved / 150.0;
if (scale < 0.01) {
scale = 0.01;
}
preMousePoint = e.getPoint();
updateAffineTransform();
repaint();
} else if ((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0) {
transX += (double) (e.getX() - preMousePoint.getX()) / scale;
transY += (double) (e.getY() - preMousePoint.getY()) / scale;
preMousePoint = e.getPoint();
updateAffineTransform();
repaint();
} else if (Globals.editMode == Constants.EditMode.PICK_LINE) {
currentMouseDraggingPoint = e.getPoint();
repaint();
}
}
@Override
public void mouseMoved(MouseEvent e) {
// Gets the value of the current logical coordinates of the mouse
try {
affineTransform.inverseTransform(e.getPoint(), currentMousePointLogic);
} catch (Exception ex) {
return;
}
if (Globals.editMode == Constants.EditMode.INPUT_LINE) {
if (Globals.lineInputMode == Constants.LineInputMode.DIRECT_V
|| Globals.lineInputMode == Constants.LineInputMode.ON_V
|| Globals.lineInputMode == Constants.LineInputMode.OVERLAP_V
|| Globals.lineInputMode == Constants.LineInputMode.PBISECTOR) {
Vector2d preV = pickCandidateV;
pickCandidateV = this.pickVertex(currentMousePointLogic);
if (pickCandidateV == null) {
if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK) {
// Arbitrary point on the line when you press the Ctrl
OriLine l = pickLine(currentMousePointLogic);
if (l != null) {
pickCandidateV = new Vector2d();
Vector2d cp = new Vector2d(currentMousePointLogic.x, currentMousePointLogic.y);
GeomUtil.DistancePointToSegment(cp, l.p0, l.p1, pickCandidateV);
}
}
}
if (pickCandidateV != preV || prePickV != null) {
repaint();
}
} else if (Globals.lineInputMode == Constants.LineInputMode.COPY_AND_PASTE) {
pickCandidateV = this.pickVertex(currentMousePointLogic);
repaint();
} else if (Globals.lineInputMode == Constants.LineInputMode.SYMMETRIC_LINE) {
Vector2d preV = pickCandidateV;
pickCandidateV = this.pickVertex(currentMousePointLogic);
if (pickCandidateV != preV) {
repaint();
}
} else if (Globals.lineInputMode == Constants.LineInputMode.TRIANGLE_SPLIT) {
Vector2d preV = pickCandidateV;
pickCandidateV = this.pickVertex(currentMousePointLogic);
if (pickCandidateV != preV) {
repaint();
}
} else if (Globals.lineInputMode == Constants.LineInputMode.BISECTOR) {
if (prePickV == null) {
Vector2d preV = pickCandidateV;
pickCandidateV = this.pickVertex(currentMousePointLogic);
if (pickCandidateV != preV || prePickV != null) {
repaint();
}
} else {
OriLine preLine = pickCandidateL;
pickCandidateL = pickLine(currentMousePointLogic);
if (preLine != pickCandidateL) {
repaint();
}
}
} else if (Globals.lineInputMode == Constants.LineInputMode.VERTICAL_LINE) {
if (prePickV == null) {
Vector2d preV = pickCandidateV;
pickCandidateV = this.pickVertex(currentMousePointLogic);
if (pickCandidateV != preV || prePickV != null) {
repaint();
}
} else {
OriLine preLine = pickCandidateL;
pickCandidateL = pickLine(currentMousePointLogic);
if (preLine != pickCandidateL) {
repaint();
}
}
} else if (Globals.lineInputMode == Constants.LineInputMode.MIRROR) {
OriLine preLine = pickCandidateL;
pickCandidateL = pickLine(currentMousePointLogic);
if (preLine != pickCandidateL) {
repaint();
}
} else if (Globals.lineInputMode == Constants.LineInputMode.BY_VALUE) {
if (Globals.subLineInputMode == Constants.SubLineInputMode.NONE) {
Vector2d preV = pickCandidateV;
pickCandidateV = this.pickVertex(currentMousePointLogic);
if (pickCandidateV != preV) {
repaint();
}
} else if (Globals.subLineInputMode == Constants.SubLineInputMode.PICK_LENGTH) {
Vector2d preV = pickCandidateV;
pickCandidateV = this.pickVertex(currentMousePointLogic);
if (pickCandidateV != preV || prePickV != null) {
repaint();
}
} else if (Globals.subLineInputMode == Constants.SubLineInputMode.PICK_ANGLE) {
Vector2d preV = pickCandidateV;
pickCandidateV = this.pickVertex(currentMousePointLogic);
if (pickCandidateV != preV) {
repaint();
}
}
}
} else if (Globals.editMode == Constants.EditMode.DELETE_LINE) {
OriLine preLine = pickCandidateL;
pickCandidateL = pickLine(currentMousePointLogic);
if (preLine != pickCandidateL) {
repaint();
}
} else if (Globals.editMode == Constants.EditMode.PICK_LINE) {
OriLine preLine = pickCandidateL;
pickCandidateL = pickLine(currentMousePointLogic);
if (preLine != pickCandidateL) {
repaint();
}
} else if (Globals.editMode == Constants.EditMode.ADD_VERTEX) {
Object[] line_vertex = new Object[2];
if (pickPointOnLine(currentMousePointLogic, line_vertex)) {
pickCandidateV = (Vector2d) line_vertex[1];
repaint();
} else {
if (pickCandidateV != null) {
pickCandidateV = null;
repaint();
}
}
} else if (Globals.editMode == Constants.EditMode.DELETE_VERTEX) {
Vector2d preV = pickCandidateV;
pickCandidateV = this.pickVertex(currentMousePointLogic);
if (pickCandidateV != preV || prePickV != null) {
repaint();
}
} else if (Globals.editMode == Constants.EditMode.EDIT_OUTLINE) {
pickCandidateV = this.pickVertex(currentMousePointLogic);
repaint();
}
}
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
double scale_ = (100.0 - e.getWheelRotation() * 5) / 100.0;
scale *= scale_;
updateAffineTransform();
repaint();
}
@Override
public void actionPerformed(ActionEvent ae) {
}
@Override
public void componentResized(ComponentEvent arg0) {
if (getWidth() <= 0 || getHeight() <= 0) {
return;
}
preSize = getSize();
// Update of the logical coordinates of the center of the screen
transX = transX - preSize.width * 0.5 + getWidth() * 0.5;
transY = transY - preSize.height * 0.5 + getHeight() * 0.5;
// Updating the image buffer
bufferImage = createImage(getWidth(), getHeight());
bufferg = (Graphics2D) bufferImage.getGraphics();
updateAffineTransform();
repaint();
}
@Override
public void componentMoved(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void componentShown(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void componentHidden(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
}