package oripa.paint.creasepattern;
import java.util.Collection;
import javax.vecmath.Vector2d;
import oripa.geom.GeomUtil;
import oripa.paint.core.PaintConfig;
import oripa.paint.creasepattern.tool.BisectorFactory;
import oripa.paint.creasepattern.tool.ElementRemover;
import oripa.paint.creasepattern.tool.LineAdder;
import oripa.paint.creasepattern.tool.LineDivider;
import oripa.paint.creasepattern.tool.LineMirror;
import oripa.paint.creasepattern.tool.LinePaster;
import oripa.paint.creasepattern.tool.LineSelectionModifier;
import oripa.paint.creasepattern.tool.LineTypeChanger;
import oripa.paint.creasepattern.tool.PainterCommandFailedException;
import oripa.paint.creasepattern.tool.RotatedLineFactory;
import oripa.paint.creasepattern.tool.SymmetricLineFactory;
import oripa.paint.creasepattern.tool.TiledLineFactory;
import oripa.paint.creasepattern.tool.TypeForChange;
import oripa.value.OriLine;
/**
* A tool to modify crease pattern (or line collection)
* @author Koji
*
*/
public class Painter {
// FIXME all methods should return success/failure
//! might be better to separate methods as service classes
/**
* reset selection mark of all lines in given collection.
* @param creasePattern
*/
public void resetSelectedOriLines(Collection<OriLine> creasePattern) {
LineSelectionModifier modifier = new LineSelectionModifier();
modifier.resetSelectedOriLines(creasePattern);
}
/**
* set {@code true} to selection mark of all lines in given collection.
* @param creasePattern
*/
public void selectAllOriLines(Collection<OriLine> creasePattern) {
LineSelectionModifier modifier = new LineSelectionModifier();
modifier.selectAllOriLines(creasePattern);
}
/**
* count how many lines are selected.
* @param creasePattern
* @return
*/
public int countSelectedLines(Collection<OriLine> creasePattern) {
LineSelectionModifier modifier = new LineSelectionModifier();
return modifier.countSelectedLines(creasePattern);
}
/**
*
* @param creasePattern
*/
public void removeSelectedLines(
Collection<OriLine> creasePattern) {
ElementRemover remover = new ElementRemover();
remover.removeSelectedLines(creasePattern);
}
/**
* add given line to crease pattern.
* All lines which cross with given line are divided at the cross points (given line is also divided).
*
* @param inputLine a line to be added
* @param creasePattern destination of inputLine
*/
public void addLine(
OriLine inputLine, Collection<OriLine> creasePattern) {
LineAdder lineAdder = new LineAdder();
lineAdder.addLine(inputLine, creasePattern);
}
public void pasteLines(
Collection<OriLine> lines, Collection<OriLine> creasePattern){
LinePaster paster = new LinePaster();
paster.paste(lines, creasePattern);
}
/**
* add mirrored lines
*
* @param baseLine a line to be the axis of symmetry
* @param lines lines to be mirrored
* @param creasePattern destination of mirrored lines
*/
public void mirrorCopyBy(OriLine baseLine,
Collection<OriLine> lines, Collection<OriLine> creasePattern) {
LineMirror mirror = new LineMirror();
Collection<OriLine> copiedLines = mirror.createMirroredLines(baseLine, lines);
LineAdder adder = new LineAdder();
adder.addAll(copiedLines, creasePattern);
}
/**
* remove given line from the collection.
* @param l
* @param creasePattern
*/
public void removeLine(
OriLine l, Collection<OriLine> creasePattern) {
ElementRemover remover = new ElementRemover();
remover.removeLine(l, creasePattern);
}
/**
* remove given vertex from the collection.
* @param v
* @param creasePattern
*/
public void removeVertex(
Vector2d v, Collection<OriLine> creasePattern) {
ElementRemover remover = new ElementRemover();
remover.removeVertex(v, creasePattern);
}
/**
* add vertex on a line
* @param line
* @param v
* @param creasePattern
* @param paperSize
* @return true if the vertex is added.
*/
public boolean addVertexOnLine(
OriLine line, Vector2d v,
Collection<OriLine> creasePattern, double paperSize) {
LineDivider divider = new LineDivider();
Collection<OriLine> dividedLines =
divider.divideLineInCollection(line, v, creasePattern, paperSize);
if (dividedLines == null) {
return false;
}
ElementRemover remover = new ElementRemover();
remover.removeLine(line, creasePattern);
LineAdder adder = new LineAdder();
adder.addAll(dividedLines, creasePattern);
return true;
}
/**
* add three inner lines of rabbit-ear molecule for given triangle
*
* @param v0
* @param v1
* @param v2
* @param creasePattern
*/
public void addTriangleDivideLines(
Vector2d v0, Vector2d v1, Vector2d v2,
Collection<OriLine> creasePattern) {
Vector2d c = GeomUtil.getIncenter(v0, v1, v2);
if (c == null) {
System.out.print("Failed to calculate incenter of the triangle");
}
LineAdder adder = new LineAdder();
adder.addLine(new OriLine(c, v0, PaintConfig.inputLineType), creasePattern);
adder.addLine(new OriLine(c, v1, PaintConfig.inputLineType), creasePattern);
adder.addLine(new OriLine(c, v2, PaintConfig.inputLineType), creasePattern);
}
/**
* add perpendicular bisector line between v0 and v1
* @param v0
* @param v1
* @param creasePattern
* @param paperSize
*/
public void addPBisector(
Vector2d v0, Vector2d v1,
Collection<OriLine> creasePattern, double paperSize) {
BisectorFactory factory = new BisectorFactory();
OriLine bisector =
factory.createPerpendicularBisector(v0, v1, paperSize);
LineAdder adder = new LineAdder();
adder.addLine(bisector, creasePattern);
}
/**
* add a bisector line from v1 to given line.
* @param v0
* @param v1
* @param v2
* @param l
* @param creasePattern
*/
public void addBisectorLine(
Vector2d v0, Vector2d v1, Vector2d v2,
OriLine l,
Collection<OriLine> creasePattern) {
BisectorFactory factory = new BisectorFactory();
OriLine bisector =
factory.createAngleBisectorLine(v0, v1, v2, l);
LineAdder adder = new LineAdder();
adder.addLine(bisector, creasePattern);
}
/**
* change type of given line.
*
* @param l
* @param from
* @param to
* @param creasePattern
*/
public void alterLineType(
OriLine l, TypeForChange from, TypeForChange to,
Collection<OriLine> creasePattern) {
LineTypeChanger changer = new LineTypeChanger();
changer.alterLineType(l, creasePattern, from, to);
}
/**
* v1-v2 is the symmetry line, v0-v1 is the subject to be copied.
* @param v0
* @param v1
* @param v2
* @param creasePattern
*
* @return true if line is added
* @throws PainterCommandFailedException
*/
public boolean addSymmetricLine(
Vector2d v0, Vector2d v1, Vector2d v2,
Collection<OriLine> creasePattern) {
SymmetricLineFactory factory = new SymmetricLineFactory();
OriLine symmetricLine;
try {
symmetricLine = factory.createSymmetricLine(v0, v1, v2, creasePattern);
} catch (PainterCommandFailedException comEx) {
return false;
}
LineAdder adder = new LineAdder();
adder.addLine(symmetricLine, creasePattern);
return true;
}
/**
* add possible rebouncing of the fold.
*
* @param v0 terminal point of the line to be copied
* @param v1 connecting point of symmetry line and the line to be copied.
* @param v2 terminal point of symmetry line
* @param startV
* @param creasePattern
*
* @return true if line is added
* @throws PainterCommandFailedException
*/
public boolean addSymmetricLineAutoWalk(
Vector2d v0, Vector2d v1, Vector2d v2, Vector2d startV,
Collection<OriLine> creasePattern) {
SymmetricLineFactory factory = new SymmetricLineFactory();
Collection<OriLine> autoWalkLines;
try {
autoWalkLines=
factory.createSymmetricLineAutoWalk(
v0, v1, v2, startV, creasePattern);
} catch (PainterCommandFailedException comEx) {
return false;
}
LineAdder adder = new LineAdder();
adder.addAll(autoWalkLines, creasePattern);
return true;
}
/**
* add copy of selected lines with a rotation around specified center point.
* For a line l, this method creates rotatedLine(l, angleDeg * i) for i = 1 ... repetitionCount.
*
* @param cx x of center
* @param cy y of center
* @param angleDeg amount of rotation in degrees
* @param repetitionCount
* @param creasePattern
* @param paperSize
*
* @return rotated lines
*/
//TODO a collection of selected line should be a parameter as like mirror copy.
public void copyWithRotation(
double cx, double cy, double angleDeg, int repetitionCount,
Collection<OriLine> creasePattern, double paperSize) {
RotatedLineFactory factory = new RotatedLineFactory();
Collection<OriLine> copiedLines = factory.createRotatedLines(
cx, cy, angleDeg, repetitionCount, creasePattern, paperSize);
LineSelectionModifier selectionModifier = new LineSelectionModifier();
selectionModifier.resetSelectedOriLines(creasePattern);
LineAdder adder = new LineAdder();
adder.addAll(copiedLines, creasePattern);
}
/**
* add copy of selected lines with tiling.
* @param row
* @param col
* @param interX
* @param interY
* @param creasePattern
* @param paperSize
*/
public void copyWithTiling(
int row, int col, double interX, double interY,
Collection<OriLine> creasePattern, double paperSize) {
TiledLineFactory factory = new TiledLineFactory();
Collection<OriLine> copiedLines =
factory.createTiledLines(
row, col, interX, interY,
creasePattern, paperSize);
LineAdder adder = new LineAdder();
adder.addAll(copiedLines, creasePattern);
}
/**
* add copy of selected lines as the paper is filled out.
* @param lines
* @param creasePattern
* @param paperSize
*/
public void fillOut(
Collection<OriLine> lines,
Collection<OriLine> creasePattern, double paperSize) {
TiledLineFactory factory = new TiledLineFactory();
Collection<OriLine> copiedLines =
factory.createFullyTiledLines(lines, creasePattern, paperSize);
LineAdder adder = new LineAdder();
adder.addAll(copiedLines, creasePattern);
}
}