package Connectivity;
import java.util.ArrayList;
import Command.LDrawPart;
import Common.Matrix4;
import Common.Vector3f;
import LDraw.Support.MatrixMath;
import LDraw.Support.type.LDrawGridTypeT;
public class MatrixItem implements Cloneable, IConnectivity {
protected int altitude;
protected int occupiedArea;
protected int shape;
protected int columnIndex;
protected int rowIndex;
protected Connectivity parent;
protected MatrixItem connectedMatrix = null;
protected Vector3f currentPos = new Vector3f();
protected Vector3f cachedLocalPos = null;
public MatrixItem() {
altitude = occupiedArea = shape = 0;
this.parent = null;
}
public MatrixItem(Connectivity parent) {
this();
this.parent = parent;
}
public void parseString(String string) {
if (string == null)
return;
String tokens[] = string.split(":");
if (tokens.length == 0)
return;
altitude = Integer.parseInt(tokens[0]);
if (tokens.length == 3) {
occupiedArea = Integer.parseInt(tokens[1]);
shape = Integer.parseInt(tokens[2]);
} else if (tokens.length == 2) {
occupiedArea = Integer.parseInt(tokens[1]);
shape = 0;
} else {
occupiedArea = shape = 0;
}
}
public int getAltitude() {
return altitude;
}
public void setAltitude(int altitude) {
this.altitude = altitude;
}
public int getOccupiedArea() {
return occupiedArea;
}
public void setOccupiedArea(int occupiedArea) {
this.occupiedArea = occupiedArea;
}
public int getShape() {
return shape;
}
public void setShape(int shape) {
this.shape = shape;
}
public int getColumnIndex() {
return columnIndex;
}
public void setColumnIndex(int columnIndex) {
this.columnIndex = columnIndex;
}
public int getRowIndex() {
return rowIndex;
}
public void setRowIndex(int rowIndex) {
this.rowIndex = rowIndex;
}
public Connectivity getParent() {
return parent;
}
public Object clone() throws CloneNotSupportedException {
MatrixItem a = (MatrixItem) super.clone();
a.parent = parent;
a.currentPos = (Vector3f) currentPos.clone();
return a;
}
@Override
public Direction6T getDirection() {
if (parent != null)
return parent.getDirection();
// TODO Auto-generated method stub
return null;
}
@Override
public void updateConnectivityOrientationInfo() {
if (parent == null)
return;
if (parent.parent == null)
return;
// update curentPos
Vector3f newPos = getCurrentPos(parent.parent.transformationMatrix());
currentPos.set(newPos);
}
@Override
public Vector3f getCurrentPos() {
return currentPos;
}
@Override
public ConnectivityTestResultT isConnectable(
ArrayList<IConnectivity> connectors) {
if (connectors == null)
return ConnectivityTestResultT.None;
if (connectors.size() == 0)
return ConnectivityTestResultT.None;
if (connectors.size() == 1)
return isConnectable(connectors.get(0));
MatrixItem mergedMatrixItem = null;
for (int i = 0; i < connectors.size(); i++) {
MatrixItem item = (MatrixItem) connectors.get(i);
if (item.getDirection() != getDirection())
continue;
if (mergedMatrixItem == null) {
try {
mergedMatrixItem = (MatrixItem) item.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mergedMatrixItem.setParent(item.getParent());
} else {
mergedMatrixItem.setOccupiedArea(mergedMatrixItem
.getOccupiedArea() + item.getOccupiedArea());
if (mergedMatrixItem.getOccupiedArea() > 4)
mergedMatrixItem.setOccupiedArea(4);
}
}
if (mergedMatrixItem == null)
return ConnectivityTestResultT.None;
return isConnectable(mergedMatrixItem);
}
@Override
public ConnectivityTestResultT isConnectable(
ArrayList<IConnectivity> connectors, Matrix4 partTransformMatrix) {
return isConnectable(connectors);
}
@Override
public ConnectivityTestResultT isConnectable(IConnectivity connector) {
if (parent == null) {
System.out.println("parent is null");
return ConnectivityTestResultT.False;
}
if (MatrixItem.class.isInstance(connector) == false) {
System.out.println("It is not a MatrixItem");
return ConnectivityTestResultT.False;
}
MatrixItem matrixItem_Stud = null;
MatrixItem matrixItem_Hole = null;
if (Stud.class.isInstance(parent)) {
// stud to stud check
if (Stud.class.isInstance(((MatrixItem) connector).getParent()))
return ConnectivityTestResultT.None;
matrixItem_Stud = this;
matrixItem_Hole = (MatrixItem) connector;
} else {
// hole to hole check
if (Hole.class.isInstance(((MatrixItem) connector).getParent())) {
// if (getOccupiedArea()
// + ((MatrixItem) connector).getOccupiedArea() > 4)
// return ConnectivityTestResultT.False;
// else
return ConnectivityTestResultT.None;
}
matrixItem_Stud = (MatrixItem) connector;
matrixItem_Hole = this;
}
switch (matrixItem_Stud.getAltitude()) {
case 1:
switch (matrixItem_Hole.getAltitude()) {
case 5:
case 7:
case 9:
case 15:
case 17:
return ConnectivityTestResultT.True;
default:
return ConnectivityTestResultT.None;
}
case 0:
case 2:
case 3:
case 9:
switch (matrixItem_Hole.getAltitude()) {
case 5:
case 7:
case 9:
case 15:
case 16:
case 17:
return ConnectivityTestResultT.True;
default:
return ConnectivityTestResultT.None;
}
case 18:
switch (matrixItem_Hole.getAltitude()) {
case 5:
case 8:
return ConnectivityTestResultT.True;
default:
return ConnectivityTestResultT.None;
}
case 23:
return ConnectivityTestResultT.None;
case 29:
return ConnectivityTestResultT.None;
}
System.out.println("Unknown MatrixItem");
System.out.println(matrixItem_Stud.getAltitude() + "<stud-hole>"
+ matrixItem_Hole.getAltitude());
return ConnectivityTestResultT.None;
}
@Override
public ConnectivityTestResultT isConnectable(IConnectivity connector,
Matrix4 partTransformMatrix) {
ConnectivityTestResultT result = isConnectable(connector);
if (result != ConnectivityTestResultT.True)
return result;
Matrix4 rotationMatrix = getTransformMatrixForConnecting(
(MatrixItem) connector, partTransformMatrix);
if (rotationMatrix == null) {
return ConnectivityTestResultT.False;
}
if (getCurrentPos(partTransformMatrix).sub(
getCurrentPos(rotationMatrix)).length() > 2f) {
return ConnectivityTestResultT.False;
}
return result;
}
public void setParent(Connectivity conn_copy) {
this.parent = conn_copy;
}
@Override
public Direction6T getDirection(Matrix4 partTransformMatrix) {
if (parent != null)
return parent.getDirection(partTransformMatrix);
return null;
}
@Override
public Vector3f getCurrentPos(Matrix4 partTransformMatrix) {
Vector3f newPos = cachedLocalPos;
if (newPos == null) {
newPos = new Vector3f(rowIndex
* LDrawGridTypeT.Medium.getXZValue(), 0, -columnIndex
* LDrawGridTypeT.Medium.getXZValue());
cachedLocalPos = newPos;
}
newPos = getTransformMatrix().transformPoint(newPos);
newPos = partTransformMatrix.transformPoint(newPos);
return newPos;
}
public float distance(Vector3f testingPos) {
Vector3f distance = testingPos.sub(getCurrentPos());
return distance.dot(distance);
}
public Matrix4 getTransformMatrixForConnecting(MatrixItem existMatrixItem,
Matrix4 initialTransformOfPart) {
Connectivity existingConn = existMatrixItem.getParent();
Matrix4 newTransform = getRotationMatrixForConnection(existingConn,
initialTransformOfPart);
if (newTransform != null) {
// newTransform.translate(initialTransformOfPart.element[3][0],
// initialTransformOfPart.element[3][1],
// initialTransformOfPart.element[3][2]);
Vector3f realMatchingPosOfExistingMatrixItem = existMatrixItem
.getCurrentPos();
Vector3f realPosOfTestingMatrixItem = getCurrentPos(newTransform);
Vector3f newPos = realMatchingPosOfExistingMatrixItem
.sub(realPosOfTestingMatrixItem);
newTransform.translate(newPos.x, newPos.y, newPos.z);
}
return newTransform;
}
public Matrix4 getRotationMatrixForConnection(Connectivity existingConn,
Matrix4 initialTransformMatrixOfPart) {
Matrix4 newMatrix = new Matrix4(initialTransformMatrixOfPart);
newMatrix.element[3][0] = newMatrix.element[3][1] = newMatrix.element[3][2] = 0;
LDrawPart existingPart = existingConn.getParent();
Matrix4 existingConnTransformMatrix = Matrix4.multiply(
existingConn.getTransformMatrix(),
existingPart.transformationMatrix());
for (int i = 0; i < 3; i++)
existingConnTransformMatrix.element[3][i] = 0;
Matrix4 testingConnTransformMatrix = Matrix4.multiply(
getTransformMatrix(), initialTransformMatrixOfPart);
for (int i = 0; i < 3; i++)
testingConnTransformMatrix.element[3][i] = 0;
// if (getDirectionVector().equals(existingConn.getDirectionVector()) ==
// false)
// return null;
Matrix4 candidate = Matrix4.multiply(
Matrix4.inverse(getTransformMatrix()),
existingConnTransformMatrix);
Direction6T direction6tCandidate = Direction6T
.getDirectionOfTransformMatrix(candidate);
Direction6T direction6tInitial = Direction6T
.getDirectionOfTransformMatrix(initialTransformMatrixOfPart);
if (getDirection().getValue() == direction6tCandidate.getValue()
|| getDirection().getValue() == direction6tInitial.getValue())
if (direction6tCandidate.getValue() != direction6tInitial
.getValue()) {
// System.out.println(getDirection());
// System.out.println(Direction6T.getDirectionOfTransformMatrix(
// candidate).getValue());
// System.out.println(Direction6T.getDirectionOfTransformMatrix(
// initialTransformMatrixOfPart).getValue());
// System.out.println("#####################");
return null;
}
for (int i = 0; i < 3; i++)
candidate.element[3][i] = 0;
Matrix4 initMatrix = new Matrix4(initialTransformMatrixOfPart);
for (int i = 0; i < 3; i++)
initMatrix.element[3][i] = 0;
// System.out.println(getCurrentPos(initMatrix));
// System.out.println(getCurrentPos(candidate));
// System.out.println("#####################");
ArrayList<Matrix4> candidateForRotation = new ArrayList<Matrix4>();
candidateForRotation.add(candidate);
for (int i = 0; i < 3; i++) {
candidate = new Matrix4(candidate);
candidate.rotate((float) Math.toRadians(90),
existingConn.getDirectionVector());
candidateForRotation.add(candidate);
}
float posDiff = -1;
float posDiff2 = -1;
for (Matrix4 matrix : candidateForRotation) {
posDiff2 = matrix.getDifferentValueForRotation(initMatrix);
if (posDiff < 0) {
posDiff = posDiff2;
newMatrix = matrix;
} else if (posDiff > posDiff2 + 0.2f) {
posDiff = posDiff2;
newMatrix = matrix;
}
}
return newMatrix;
}
@Override
public Vector3f getDirectionVector() {
return getParent().getDirectionVector();
}
@Override
public Vector3f getDirectionVector(Matrix4 partTransformMatrix) {
return getParent().getDirectionVector(partTransformMatrix);
}
@Override
public Matrix4 transformationMatrixOfPart() {
return parent.transformationMatrixOfPart();
}
@Override
public void moveTo(Vector3f moveByInWorld) {
updateConnectivityOrientationInfo();
Vector3f diff = getCurrentPos().sub(parent.getCurrentPos());
Vector3f newMoveByInWorld = moveByInWorld.sub(diff);
parent.moveTo(newMoveByInWorld);
}
@Override
public void moveBy(Vector3f moveByInWorld) {
updateConnectivityOrientationInfo();
Vector3f diff = getCurrentPos().sub(parent.getCurrentPos());
Vector3f newMoveByInWorld = moveByInWorld.sub(diff);
parent.moveBy(newMoveByInWorld);
}
@Override
public void rotateBy(float angle, Vector3f roationVector) {
parent.rotateBy(angle, roationVector);
}
public Connectivity getConnectivity() {
return parent;
}
public Matrix4 getTransformMatrix() {
return parent.getTransformMatrix();
}
public MatrixItem getConnectedConnectivity() {
return connectedMatrix;
}
public void setConnectedConnectivity(IConnectivity connectedMatrix) {
this.connectedMatrix = (MatrixItem) connectedMatrix;
}
}