package Connectivity; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Map.Entry; import Builder.BrickSelectionManager; import Builder.BuilderConfigurationManager; import Command.LDrawPart; import Command.PartTypeT; import Common.Box3; import Common.Matrix4; import Common.Vector2f; import Common.Vector3f; import ConnectivityEditor.Connectivity.AxleT; import Grouping.ConnectionPoint; import LDraw.Support.LDrawUtilities; import LDraw.Support.MatrixMath; import LDraw.Support.type.LDrawGridTypeT; import Window.GlobalMousePosition; import Window.MOCBuilder; public class GlobalConnectivityManager { private static GlobalConnectivityManager _instance = null; public synchronized static GlobalConnectivityManager getInstance() { if (_instance == null) _instance = new GlobalConnectivityManager(); return _instance; } private ArrayList<LDrawPart> allPartList; private HashMap<Vector3f, ArrayList<LDrawPart>> partListMap; private HashMap<Vector3f, ArrayList<MatrixItem>> studCoordinateMap; private HashMap<Vector3f, ArrayList<MatrixItem>> holeCoordinateMap; private HashMap<IConnectivity, Vector3f> oldPosMap; private GlobalConnectivityManager() { allPartList = new ArrayList<LDrawPart>(); partListMap = new HashMap<Vector3f, ArrayList<LDrawPart>>(); studCoordinateMap = new HashMap<Vector3f, ArrayList<MatrixItem>>(); holeCoordinateMap = new HashMap<Vector3f, ArrayList<MatrixItem>>(); oldPosMap = new HashMap<IConnectivity, Vector3f>(); } public void addPart(LDrawPart part) { addPart(part, true); } public void addPart(LDrawPart part, boolean updateMatrix) { if (LDrawPart.class.isInstance(part)) { synchronized (allPartList) { allPartList.add(part); } if (updateMatrix) updateMatrix(part, false); } } public boolean checkCollision(LDrawPart part, Matrix4 testingTransform) { boolean isCollide = false; isCollide = checkBoundingBoxIntersection(part, testingTransform); if (isCollide == false) return isCollide; if (part.getCacheType() == PartTypeT.PartTypeSubmodel) { isCollide = false; for (LDrawPart subPart : LDrawUtilities.extractLDrawPartListModel( part.getCacheModel(), false)) if (checkCollision(subPart, Matrix4.multiply( subPart.transformationMatrix(), testingTransform))) return true; } else isCollide = CheckCollisionBox(part, testingTransform); return isCollide; } private boolean checkBoundingBoxIntersection(LDrawPart part, Matrix4 testingTransform) { Box3 testPartBoundingBox = part.boundingBox3(testingTransform); boolean isIntersected = false; for (LDrawPart adjacentPart : getAdjacentPartList(testPartBoundingBox)) { if (adjacentPart == part) continue; if (adjacentPart.isDraggingPart()) continue; if (adjacentPart.isSelected()) continue; Box3 boundingBox = ((LDrawPart) adjacentPart).boundingBox3(); if (boundingBox == null) continue; if (LDrawUtilities.isIntersected(testPartBoundingBox, boundingBox)) { isIntersected = true; break; } } return isIntersected; } public boolean CheckCollisionBox(LDrawPart srcPart, Matrix4 testingPartTransformMatrix) { ArrayList<CollisionBox> srcboxes = srcPart.getCollisionBoxList(); if (srcboxes == null || srcboxes.size() == 0) return false; Box3 boundingBox = srcPart.boundingBox3(testingPartTransformMatrix); ArrayList<LDrawPart> adjacentPartList = getAdjacentPartList(boundingBox); if (adjacentPartList == null) return false; adjacentPartList.remove(srcPart); HashMap<LDrawPart, ArrayList<CollisionBox>> destBoxesMap = new HashMap<LDrawPart, ArrayList<CollisionBox>>(); for (LDrawPart destpart : adjacentPartList) { if (destpart.isSelected()) continue; destBoxesMap.put(destpart, destpart.getCollisionBoxList( Matrix4.getIdentityMatrix4(), boundingBox)); } for (int i = 0; i < srcboxes.size(); i++) { CollisionBox srcCollisionBox = srcboxes.get(i); Vector3f[] srcvAxisDir = srcCollisionBox .MakeDirection(testingPartTransformMatrix); float[] srcfAxisLen = srcCollisionBox.GetAxisLength(); Vector3f srcCenter = srcCollisionBox .getCenter(testingPartTransformMatrix); for (LDrawPart destpart : adjacentPartList) { if (destpart.isSelected()) continue; ArrayList<CollisionBox> destboxes = destBoxesMap.get(destpart); if (destboxes == null || destboxes.size() == 0) continue; for (int k = 0; k < destboxes.size(); k++) { CollisionBox destCollisionBox = destboxes.get(k); Vector3f[] destvAxisDir = destCollisionBox .MakeDirection(destpart.transformationMatrix()); float[] destfAxisLen = destCollisionBox.GetAxisLength(); Vector3f destCenter = destCollisionBox.getCenter(destpart); if (CollisionBox.CheckOBBCollision(srcCollisionBox, srcCenter, srcvAxisDir, srcfAxisLen, destCollisionBox, destCenter, destvAxisDir, destfAxisLen) == true) { return true; } } } } return false; } public void clear() { clear(true); } public void clear(boolean updateMatrix) { synchronized (allPartList) { allPartList.clear(); } synchronized (studCoordinateMap) { studCoordinateMap.clear(); } synchronized (holeCoordinateMap) { holeCoordinateMap.clear(); } synchronized (partListMap) { partListMap.clear(); } if (updateMatrix) updateMatrixAll(); } public final ArrayList<LDrawPart> getAdjacentPartList(Box3 boundingBox) { ArrayList<LDrawPart> partList = new ArrayList<LDrawPart>(); Vector3f coarseMin = LDrawGridTypeT.getSnappedPos(boundingBox.getMin(), LDrawGridTypeT.CoarseX10); Vector3f coarseMax = LDrawGridTypeT.getSnappedPos(boundingBox.getMax(), LDrawGridTypeT.CoarseX10); Vector3f partPos; for (int x = Math.round(coarseMin.x); x <= Math.round(coarseMax.x); x += LDrawGridTypeT.CoarseX10 .getXZValue()) for (int y = Math.round(coarseMin.y); y <= Math.round(coarseMax.y); y += LDrawGridTypeT.CoarseX10 .getYValue()) for (int z = Math.round(coarseMin.z); z <= Math .round(coarseMax.z); z += LDrawGridTypeT.CoarseX10 .getXZValue()) { partPos = new Vector3f(x, y, z); if (partListMap.containsKey(partPos)) { for (LDrawPart part : this.partListMap.get(partPos)) { if (part.boundingBox3() == boundingBox) continue; if (LDrawUtilities.isIntersected(boundingBox, part.boundingBox3())) if (partList.contains(part) == false) partList.add(part); } } } return partList; } // part ���� ���� ����. // testPosOfPart ���� ���� ������ ���ο� ��ǥ. public Matrix4 getClosestConnectablePos(LDrawPart part, Vector3f testPosOfPart) { try { // hittedPos ���콺�� ����Ű�� ��ǥ . Vector2f mousePos = GlobalMousePosition.getInstance().getPos(); Vector3f hittedWorldPos = MOCBuilder.getInstance().getHittedPos( mousePos.getX(), mousePos.getY(), true); ConnectivityTestResult testResult = null; if (BuilderConfigurationManager.getInstance().isUseConnectivity()) testResult = isConnectable(part, testPosOfPart, hittedWorldPos); if (testResult != null && testResult.getResultType() == ConnectivityTestResultT.True) { return testResult.getTransformMatrix(); } if (MatrixMath.compareFloat(hittedWorldPos.y, 0) != 0) { LDrawPart minPart = BrickSelectionManager.getInstance() .getPartHavingMinY(); float offsetY = -minPart.boundingBox3( minPart.getRotationMatrix()).getMax().y; testPosOfPart.y = hittedWorldPos.y + offsetY + part.position().sub(minPart.position()).y; testPosOfPart = LDrawGridTypeT .getSnappedPos(testPosOfPart, BuilderConfigurationManager.getInstance() .getGridUnit()); Matrix4 newTransform = BrickSelectionManager.getInstance() .getStartMoveTransformMatrix(part); newTransform.element[3][0] = testPosOfPart.x; newTransform.element[3][1] = testPosOfPart.y; newTransform.element[3][2] = testPosOfPart.z; return newTransform; } if (BuilderConfigurationManager.getInstance().isUseConnectivity() && BuilderConfigurationManager.getInstance() .isUseDefaultBaseplate() && testResult == null) { MatrixItem minItem = BrickSelectionManager.getInstance() .getMatrixItemHavingMinY(); if (minItem != null) { Vector3f newPosOfMinItem = minItem .getCurrentPos( minItem.getParent().getParent() .getRotationMatrix()) .add(testPosOfPart) .add(LDrawGridTypeT.Coarse.getXZValue() / 2, 0, LDrawGridTypeT.Coarse.getXZValue() / 2); Vector3f snappedItemPosDiff = newPosOfMinItem .sub(LDrawGridTypeT.getSnappedPos(newPosOfMinItem, LDrawGridTypeT.Coarse)); Matrix4 newTransform = BrickSelectionManager.getInstance() .getStartMoveTransformMatrix(part); newTransform.element[3][0] = testPosOfPart.x - snappedItemPosDiff.x; newTransform.element[3][1] = testPosOfPart.y; newTransform.element[3][2] = testPosOfPart.z - snappedItemPosDiff.z; return newTransform; } } // default LDrawPart minPart = BrickSelectionManager.getInstance() .getPartHavingMinY(); Vector3f boundOfMinPart = new Vector3f(); try { boundOfMinPart = minPart .boundingBox3(minPart.getRotationMatrix()).getMax() .add(testPosOfPart); } catch (Exception e) { e.printStackTrace(); } Vector3f snappedItemPosDiff = boundOfMinPart.sub(LDrawGridTypeT .getSnappedPos(boundOfMinPart, BuilderConfigurationManager .getInstance().getGridUnit())); Matrix4 newTransform = BrickSelectionManager.getInstance() .getStartMoveTransformMatrix(part); newTransform.element[3][0] = testPosOfPart.x - snappedItemPosDiff.x; newTransform.element[3][1] = testPosOfPart.y; newTransform.element[3][2] = testPosOfPart.z - snappedItemPosDiff.z; return newTransform; } catch (Exception e) { e.printStackTrace(); return null; } } public ArrayList<LDrawPart> getPartList() { synchronized (allPartList) { ArrayList<LDrawPart> copy = new ArrayList<LDrawPart>(allPartList); return copy; } } private ArrayList<ConnectivityTestResult> getPotentialConnectibleList( final Vector3f hittedPos, LDrawPart part, Matrix4 initialTransformMatrixOfTestingPart) { ArrayList<ConnectivityTestResult> testResults = new ArrayList<ConnectivityTestResult>(); ArrayList<IConnectivity> testingPartConnList = new ArrayList<IConnectivity>(); testingPartConnList.addAll(BrickSelectionManager.getInstance() .getConnectivityManager(hittedPos).getConnectivityList()); testingPartConnList.addAll(BrickSelectionManager.getInstance() .getConnectivityManager(hittedPos) .getConnectivityMatrixItemList()); if (testingPartConnList.isEmpty()) return null; ArrayList<Connectivity> existingConnList = new ArrayList<Connectivity>(); ArrayList<MatrixItem> existingMatrixItemList = new ArrayList<MatrixItem>(); for (LDrawPart adjacentPart : getAdjacentPartList(part .boundingBox3(initialTransformMatrixOfTestingPart))) { if (adjacentPart == part) continue; if (adjacentPart.isSelected()) continue; if (adjacentPart.getConnectivityList() != null) for (Connectivity conn : adjacentPart.getConnectivityList()) if (conn instanceof ICustom2DField) { } else existingConnList.add(conn); if (adjacentPart.getConnectivityMatrixItemList() != null) for (MatrixItem matrixItem : adjacentPart .getConnectivityMatrixItemList()) if (matrixItem.getCurrentPos().sub(hittedPos).length() <= LDrawGridTypeT.Coarse .getYValue()) existingMatrixItemList.add(matrixItem); } ArrayList<IConnectivity> existingTestibleItemList = new ArrayList<IConnectivity>(); existingTestibleItemList.addAll(existingConnList); existingTestibleItemList.addAll(existingMatrixItemList); Collections.sort(existingTestibleItemList, new Comparator<IConnectivity>() { @Override public int compare(IConnectivity arg0, IConnectivity arg1) { return MatrixMath.compareFloat( arg0.distance(hittedPos), arg1.distance(hittedPos)); } }); // System.out.println("testingPos: "+testingPos); // System.out.println("testingMatrixItemList: " // + testingPartConnList.size()); // System.out.println("existingMatrixItemList: " // + existingTestibleItemList.size()); for (IConnectivity existingTestibleItem : existingTestibleItemList) { for (IConnectivity testingPartConn : testingPartConnList) { if (MatrixItem.class.isInstance(existingTestibleItem) && MatrixItem.class.isInstance(testingPartConn) == true) { if (existingTestibleItem.isConnectable(testingPartConn) == ConnectivityTestResultT.True) { ConnectivityTestResult testResult = new ConnectivityTestResult(); Matrix4 newTransform = ((MatrixItem) testingPartConn) .getTransformMatrixForConnecting( (MatrixItem) existingTestibleItem, initialTransformMatrixOfTestingPart); if (newTransform != null) { testResult .setResultType(ConnectivityTestResultT.True); testResult .setTestPos(initialTransformMatrixOfTestingPart .transformPoint(new Vector3f(0, 0, 0))); if (testingPartConn.getConnectivity().getParent() != part) { Vector3f newPos = part.position().sub( testingPartConn.getConnectivity() .getParent().position()); newTransform.translate(newPos.x, newPos.y, newPos.z); } testResult.setTransformMatrix(newTransform); testResults.add(testResult); } } } else if (Connectivity.class.isInstance(existingTestibleItem) && Connectivity.class.isInstance(testingPartConn) == true) { if (existingTestibleItem.isConnectable(testingPartConn) == ConnectivityTestResultT.True) { ConnectivityTestResult testResult = new ConnectivityTestResult(); testResult.setResultType(ConnectivityTestResultT.True); Matrix4 newTransform = ((Connectivity) testingPartConn) .getTransformMatrixForSnapConnecting( (Connectivity) existingTestibleItem, initialTransformMatrixOfTestingPart); if (newTransform != null) { if (testingPartConn.getConnectivity().getParent() != part) { Vector3f newPos = part.position().sub( testingPartConn.getConnectivity() .getParent().position()); newTransform.translate(newPos.x, newPos.y, newPos.z); } testResult.setTransformMatrix(newTransform); testResults.add(testResult); } } } } if (testResults.size() != 0) break; } return testResults; } public ConnectivityTestResult isConnectable(LDrawPart part) { if (part == null) return new ConnectivityTestResult(ConnectivityTestResultT.False); ConnectivityTestResult testResult = isConnectable_Exact(part, part.transformationMatrix()); return testResult; } private ConnectivityTestResult isConnectable(LDrawPart part, Vector3f testingPosOfPart, Vector3f hittedPos) { Matrix4 testingPartInitialTransforMatrix = null; testingPartInitialTransforMatrix = BrickSelectionManager.getInstance() .getStartMoveTransformMatrix(part); if (testingPartInitialTransforMatrix == null) testingPartInitialTransforMatrix = part.transformationMatrix(); testingPartInitialTransforMatrix = new Matrix4( testingPartInitialTransforMatrix); testingPartInitialTransforMatrix.element[3][0] = testingPosOfPart.x; testingPartInitialTransforMatrix.element[3][1] = testingPosOfPart.y; testingPartInitialTransforMatrix.element[3][2] = testingPosOfPart.z; ConnectivityTestResult testResult = isConnectable_Potential(hittedPos, part, testingPartInitialTransforMatrix); return testResult; } public ConnectivityTestResult isConnectable_Exact(LDrawPart part, Matrix4 testingPartTransformMatrix) { ConnectivityTestResult testResult = null; // ArrayList<Connectivity> connectivityList = // part.getConnectivityList(); // if (connectivityList.isEmpty() // && part.getCacheType() != PartTypeT.PartTypeSubmodel) // return new ConnectivityTestResult(); // bounding box test if (testResult == null) testResult = new ConnectivityTestResult(); if (checkBoundingBoxIntersection(part, testingPartTransformMatrix) == false) { testResult.setResultType(ConnectivityTestResultT.True); testResult.setTransformMatrix(testingPartTransformMatrix); // System.out.println("bounding Box Test Pass"); return testResult; } // collision box test if (testResult.getResultType() != ConnectivityTestResultT.False) { if (BuilderConfigurationManager.getInstance().isUseCollision()) // if (CheckCollisionBox(part, testingPartTransformMatrix) == // true) { if (checkCollision(part, testingPartTransformMatrix) == true) { testResult.setResultType(ConnectivityTestResultT.False); testResult.setMsg("Collision_2"); } } return testResult; } private ConnectivityTestResult isConnectable_Potential(Vector3f hittedPos, LDrawPart part, Matrix4 testingPartInitialTransformMatrix) { ConnectivityTestResult testResult = null; ArrayList<Connectivity> testingPartConnectivityList = part .getConnectivityList(); if (testingPartConnectivityList.isEmpty()) return new ConnectivityTestResult(); ArrayList<ConnectivityTestResult> potentialTestResults = new ArrayList<ConnectivityTestResult>(); ArrayList<ConnectivityTestResult> potentialTestResultsTemp = getPotentialConnectibleList( hittedPos, part, testingPartInitialTransformMatrix); // System.out.println("potentialTestResultsTemp: " // + potentialTestResultsTemp.size()); // connectivity test if (potentialTestResultsTemp != null) { for (ConnectivityTestResult tempResult : potentialTestResultsTemp) { boolean isContains = false; for (ConnectivityTestResult tempResult2 : potentialTestResults) { if (tempResult.getTransformMatrix().equals( tempResult2.getTransformMatrix())) { isContains = true; break; } } if (isContains == false) potentialTestResults.add(tempResult); } } // System.out.println("############################"); // System.out // .println("TestTransform"); // System.out.println(testingPartInitialTransformMatrix); // if (potentialTestResults.size() != 0) // System.out.println("Potential ListSize: " // + potentialTestResults.size()); float minimumDistance = Float.MAX_VALUE; Vector3f distanceVector; float distance; boolean isMoreClosed = false; for (ConnectivityTestResult testResultTemp : potentialTestResults) { ConnectivityTestResultT isConnectible = ConnectivityTestResultT.True; isMoreClosed = false; distanceVector = testingPartInitialTransformMatrix .getDefaultTransformPos().sub( testResultTemp.getTransformMatrix().transformPoint( new Vector3f())); distance = distanceVector.dot(distanceVector); if (Direction6T .getDirectionOfTransformMatrix(testingPartInitialTransformMatrix) != Direction6T .getDirectionOfTransformMatrix(testResultTemp .getTransformMatrix())) distance *= 1.2f; if (distance < minimumDistance) isMoreClosed = true; else continue; if (isConnectible == ConnectivityTestResultT.True) { // System.out.println(testResultTemp.getTransformMatrix().getDefaultTransformPos()); // collision box test if (BuilderConfigurationManager.getInstance().isUseCollision() == true && checkBoundingBoxIntersection(part, testResultTemp.getTransformMatrix()) == true) if (checkCollision(part, testResultTemp.getTransformMatrix()) == true) { isConnectible = ConnectivityTestResultT.False; // System.out.println("Collistion!: " // + testResultTemp.getTransformMatrix() // .getDefaultTransformPos()); } } if (isConnectible == ConnectivityTestResultT.True && isMoreClosed) { minimumDistance = distance; testResult = testResultTemp; } } return testResult; } public ConnectivityTestResult isConnectible_Connectivity(Connectivity conn, Matrix4 testingPartTransformMatrix) { ConnectivityTestResult testResult = new ConnectivityTestResult(); ArrayList<Connectivity> existingConnList = new ArrayList<Connectivity>(); // existingConnList �� part.boundingBox3 �ӿ� �ش��ϴ� Connectivity���� �־���. for (LDrawPart adjacentPart : getAdjacentPartList(conn.getParent() .boundingBox3(testingPartTransformMatrix))) { if (adjacentPart == conn.getParent()) continue; if (adjacentPart.isSelected()) continue; if (adjacentPart.getConnectivityList() != null) for (Connectivity connTemp : adjacentPart.getConnectivityList()) if (connTemp instanceof ICustom2DField) { } else existingConnList.add(connTemp); } for (Connectivity existItem : existingConnList) { if (existItem == conn) continue; if (conn.isConnectable(existItem, testingPartTransformMatrix) == ConnectivityTestResultT.True) { testResult.setResultType(ConnectivityTestResultT.True); break; } } return testResult; } private void removeExistingConnInfo(LDrawPart part) { // remove partListMap Box3 boundingBox = part.boundingBox3(); Vector3f coarseMin = LDrawGridTypeT.getSnappedPos(boundingBox.getMin(), LDrawGridTypeT.CoarseX10); Vector3f coarseMax = LDrawGridTypeT.getSnappedPos(boundingBox.getMax(), LDrawGridTypeT.CoarseX10); Vector3f partPos; for (int x = Math.round(coarseMin.x); x <= Math.round(coarseMax.x); x += LDrawGridTypeT.CoarseX10 .getXZValue()) { for (int y = Math.round(coarseMin.y); y <= Math.round(coarseMax.y); y += LDrawGridTypeT.CoarseX10 .getYValue()) { for (int z = Math.round(coarseMin.z); z <= Math .round(coarseMax.z); z += LDrawGridTypeT.CoarseX10 .getXZValue()) { partPos = new Vector3f(x, y, z); if (partListMap.containsKey(partPos)) { partListMap.get(partPos).remove(part); // System.out.println("RemovePart from "+partPos); } } } } ArrayList<Connectivity> connList = part.getConnectivityList(); ArrayList<MatrixItem> matrixItemList = part .getConnectivityMatrixItemList(); if (connList.isEmpty() == false) { for (Connectivity conn : connList) { if (conn instanceof ICustom2DField) continue; if (conn.getConnectedConnectivity() == null) continue; for (Connectivity eConn : conn.getConnectedConnectivity()) { eConn.removeConnectedConnectivity(conn); } conn.clearConnectedConnectivity(); } } if (matrixItemList != null) { for (MatrixItem item : matrixItemList) { if (oldPosMap.containsKey(item) == false) continue; Vector3f oldPos = oldPosMap.get(item); if (item.getParent() instanceof Stud) { if (studCoordinateMap.containsKey(oldPos)) studCoordinateMap.get(oldPos).remove(item); } else if (item.getParent() instanceof Hole) { if (holeCoordinateMap.containsKey(oldPos)) holeCoordinateMap.get(oldPos).remove(item); } if (item.getConnectedConnectivity() == null) continue; item.getConnectedConnectivity().setConnectedConnectivity(null); item.setConnectedConnectivity(null); } } } public void removePart(LDrawPart part) { removePart(part, false); } // public void updateMatrix() { // long nano = System.nanoTime(); // updateMatrix2(); // System.out.println("UpdateMatrix: " + (System.nanoTime() - nano)); // } public void removePart(LDrawPart part, boolean updateMatrix) { synchronized (allPartList) { allPartList.remove(part); } if (updateMatrix) updateMatrix(part, true); } public void updateMatrix(LDrawPart part) { updateMatrix(part, false); } public void updateMatrix(LDrawPart part, boolean remove) { long nano = System.nanoTime(); // if (remove) { // remove existing connectivity info // System.out.println("Remove Connectivity Matrix Info"); removeExistingConnInfo(part); // return; // System.out.println("remove Connectivity Matrix: " // + (System.nanoTime() - nano)); // } if (allPartList.contains(part) == false) return; // if (part.isDraggingPart()) { // return; // } // update partListMap Box3 boundingBox = part.boundingBox3(); Vector3f coarseMin = LDrawGridTypeT.getSnappedPos(boundingBox.getMin(), LDrawGridTypeT.CoarseX10); Vector3f coarseMax = LDrawGridTypeT.getSnappedPos(boundingBox.getMax(), LDrawGridTypeT.CoarseX10); Vector3f partPos; for (int x = Math.round(coarseMin.x); x <= Math.round(coarseMax.x); x += LDrawGridTypeT.CoarseX10 .getXZValue()) for (int y = Math.round(coarseMin.y); y <= Math.round(coarseMax.y); y += LDrawGridTypeT.CoarseX10 .getYValue()) for (int z = Math.round(coarseMin.z); z <= Math .round(coarseMax.z); z += LDrawGridTypeT.CoarseX10 .getXZValue()) { partPos = new Vector3f(x, y, z); if (partListMap.containsKey(partPos) == false) partListMap.put(partPos, new ArrayList<LDrawPart>()); partListMap.get(partPos).add(part); // System.out.println("Add Part to "+partPos); } ArrayList<Connectivity> existingConnList = new ArrayList<Connectivity>(); for (LDrawPart adjacentPart : getAdjacentPartList(part.boundingBox3())) { if (adjacentPart == part) continue; if (adjacentPart.isSelected()) continue; if (adjacentPart.getConnectivityList() != null) for (Connectivity conn : adjacentPart.getConnectivityList()) if (conn instanceof ICustom2DField) { } else existingConnList.add(conn); } // update position of connectivity and connected info. if (part.getConnectivityList() != null) { for (Connectivity conn : part.getConnectivityList()) { conn.updateConnectivityOrientationInfo(); if (conn instanceof ICustom2DField) continue; for (Connectivity eConn : existingConnList) { if (conn.isConnectable(eConn, part.transformationMatrix()) == ConnectivityTestResultT.True) { conn.addConnectedConnectivity(eConn); eConn.addConnectedConnectivity(conn); } } } } Vector3f finePos = null; if (part.getConnectivityMatrixItemList() != null) { for (MatrixItem item : part.getConnectivityMatrixItemList()) { item.updateConnectivityOrientationInfo(); finePos = LDrawGridTypeT.getSnappedPos(item.getCurrentPos(), LDrawGridTypeT.Fine); oldPosMap.put(item, finePos); if (item.getParent() instanceof Stud) { if (studCoordinateMap.containsKey(finePos) == false) studCoordinateMap.put(finePos, new ArrayList<MatrixItem>()); studCoordinateMap.get(finePos).add(item); if (item.altitude == 29) continue; for (Vector3f testiblePos : getTestibleSnappedPos( item.getCurrentPos(), LDrawGridTypeT.Fine)) { if (holeCoordinateMap.containsKey(testiblePos)) { for (MatrixItem eItem : holeCoordinateMap .get(testiblePos)) { if (eItem.altitude == 29) continue; if (eItem.getRowIndex() % 2 != 1 || eItem.getColumnIndex() % 2 != 1) continue; if (eItem.getCurrentPos() .sub(item.getCurrentPos()).length() < 1) { if (eItem.getDirectionVector().equals( item.getDirectionVector())) { if (eItem.getConnectedConnectivity() != null) { System.out .println(item.getParent() .getParent() .displayName() + "," + eItem.getParent() .getParent() .displayName() + ": " + eItem.getCurrentPos() .sub(item .getCurrentPos()) .length()); } item.setConnectedConnectivity(eItem); eItem.setConnectedConnectivity(item); } } } } } } else { if (holeCoordinateMap.containsKey(finePos) == false) holeCoordinateMap.put(finePos, new ArrayList<MatrixItem>()); holeCoordinateMap.get(finePos).add(item); if (item.altitude == 29) continue; if (item.getRowIndex() % 2 != 1 || item.getColumnIndex() % 2 != 1) continue; for (Vector3f testiblePos : getTestibleSnappedPos( item.getCurrentPos(), LDrawGridTypeT.Fine)) { if (studCoordinateMap.containsKey(testiblePos)) { for (MatrixItem eItem : studCoordinateMap .get(testiblePos)) { if (eItem.altitude == 29) continue; if (eItem.getCurrentPos() .sub(item.getCurrentPos()).length() < 1) { if (eItem.getDirectionVector().equals( item.getDirectionVector())) { if (eItem.getConnectedConnectivity() != null) { System.out .println(item.getParent() .getParent() .displayName() + "," + eItem.getParent() .getParent() .displayName() + ": " + eItem.getCurrentPos() .sub(item .getCurrentPos()) .length()); } item.setConnectedConnectivity(eItem); eItem.setConnectedConnectivity(item); } } } } } } } } // System.out.println("update Connectivity Matrix: " // + (System.nanoTime() - nano)); } public void updateMatrixAll() { long nano = System.nanoTime(); studCoordinateMap.clear(); holeCoordinateMap.clear(); partListMap.clear(); oldPosMap.clear(); for (int i = 0; i < allPartList.size(); i++) { ArrayList<Connectivity> connList = allPartList.get(i) .getConnectivityList(); ArrayList<MatrixItem> matrixItemList = allPartList.get(i) .getConnectivityMatrixItemList(); if (connList.isEmpty() == false) { for (Connectivity conn : connList) { if (conn instanceof ICustom2DField) continue; if (conn.getConnectedConnectivity() == null) continue; for (Connectivity eConn : conn.getConnectedConnectivity()) { eConn.removeConnectedConnectivity(conn); } conn.clearConnectedConnectivity(); } } if (matrixItemList != null) { for (MatrixItem item : matrixItemList) { if (item.getConnectedConnectivity() == null) continue; item.getConnectedConnectivity().setConnectedConnectivity( null); item.setConnectedConnectivity(null); } } } for (int i = 0; i < allPartList.size(); i++) { updateMatrix((LDrawPart) allPartList.get(i)); } // System.out.println("update All Connectivity Matrix: " // + (System.nanoTime() - nano)); } public ArrayList<LDrawPart> getConnectedPart(LDrawPart part, IConnectivity centerConn, Vector3f directionVector, boolean isForRotation) { ArrayList<LDrawPart> resultList = new ArrayList<LDrawPart>(); getConnectedPart(part, centerConn, directionVector, isForRotation, resultList); return resultList; } private ArrayList<LDrawPart> getConnectedPartBy(LDrawPart part, IConnectivity conn) { boolean isPartSelected = part.isSelected(); ArrayList<LDrawPart> resultList = new ArrayList<LDrawPart>(); if (conn == null) return resultList; if (resultList.contains(part)) return resultList; if (BuilderConfigurationManager.getInstance().isUseConnectivity() == false) return resultList; part.setSelected(true); resultList.add(part); if (conn instanceof MatrixItem && ((MatrixItem) conn).getConnectedConnectivity() != null) getConnectedPart(((MatrixItem) conn).getConnectedConnectivity() .getParent().getParent(), null, null, true, resultList); else for (Connectivity tempConn : conn.getConnectivity() .getConnectedConnectivity()) getConnectedPart(tempConn.getParent(), null, null, true, resultList); resultList.remove(part); part.setSelected(isPartSelected); return resultList; } private void getConnectedPart(LDrawPart part, IConnectivity centerConn, Vector3f directionVector, boolean isForRotation, ArrayList<LDrawPart> resultList) { if (resultList.contains(part)) return; resultList.add(part); if (part.isConnectivityInfoExist() == false) return; if (BuilderConfigurationManager.getInstance().isUseConnectivity() == false) return; for (Connectivity conn : part.getConnectivityList()) { if (conn instanceof ICustom2DField) continue; if (centerConn != null) { if (centerConn.getConnectivity() == conn) continue; if (isForRotation) { boolean isRotatable = false; if (conn instanceof Hinge || conn instanceof Ball) isRotatable = true; if (conn instanceof Axle) isRotatable = ((Axle) conn).isRotatible(); if (isRotatable) { Vector3f testVector = conn.getCurrentPos().sub( centerConn.getCurrentPos()); if (Math.abs(Math.abs(testVector.dot(directionVector)) - testVector.length()) < 1.0f) { if (directionVector.equals(conn .getDirectionVector())) continue; if (directionVector.equals(conn .getDirectionVector().scale(-1))) continue; } } } else { boolean isMovable = false; if (conn instanceof Axle || conn instanceof Slider) isMovable = true; if (isMovable) { if (directionVector.equals(conn.getDirectionVector())) continue; if (directionVector.equals(conn.getDirectionVector() .scale(-1))) continue; } } } if (conn.getConnectedConnectivity() != null) for (Connectivity eItem : conn.getConnectedConnectivity()) { if (resultList.contains(eItem.getParent())) continue; if (eItem.getParent().isSelected()) continue; getConnectedPart(eItem.getParent(), centerConn, directionVector, isForRotation, resultList); } } if (part.getConnectivityMatrixItemList() == null) return; for (MatrixItem matrixItem : part.getConnectivityMatrixItemList()) { MatrixItem eItem = matrixItem.getConnectedConnectivity(); if (centerConn != null) { if (centerConn == matrixItem) continue; if (eItem == null) continue; if (isForRotation) { Vector3f testVector = centerConn.getCurrentPos().sub( matrixItem.getCurrentPos()); if (Math.abs(Math.abs(testVector.dot(directionVector)) - testVector.length()) < 1.0f) { if (directionVector.equals(eItem.getDirectionVector())) continue; if (directionVector.equals(eItem.getDirectionVector() .scale(-1))) continue; } } } if (eItem != null) { if (eItem.getParent().getParent().isSelected()) continue; if (resultList.contains(eItem.getParent().getParent())) continue; getConnectedPart(eItem.getParent().getParent(), centerConn, directionVector, isForRotation, resultList); } } } public ArrayList<LDrawPart> getDirectlyConnectedParts(LDrawPart part) { ArrayList<LDrawPart> retList = new ArrayList<LDrawPart>(); for (ConnectionPoint point : getConnectionPoints(part)) if (retList.contains(point.getPart()) == false) retList.add(point.getPart()); return retList; } public ArrayList<LDrawPart> getDirectlyConnectedPartsExceptCustom2d( LDrawPart part) { ArrayList<LDrawPart> retList = new ArrayList<LDrawPart>(); for (ConnectionPoint point : getConnectionPoints(part)) if (point.getFrom() instanceof ICustom2DField == false) retList.add(point.getPart()); return retList; } // // public float getLowestConnectionPos(LDrawPart part, // ArrayList<LDrawPart> partList) { // float lowestPos = -Float.MAX_VALUE; // for (Connectivity conn : part.getConnectivityList()) { // Vector3f pos_Medium = null; // Vector3f pos_Fine = null; // // if (conn instanceof ICustom2DField) { // ConcurrentHashMap<Vector3f, ConcurrentHashMap<Vector3f, // ArrayList<MatrixItem>>> coordinateMap = null; // ConcurrentHashMap<Vector3f, ArrayList<MatrixItem>> fineCoordinateMap = // null; // if (conn instanceof Hole) // coordinateMap = studCoordinateMap; // else // coordinateMap = holeCoordinateMap; // // MatrixItem[][] matrixItems = ((ICustom2DField) conn) // .getMatrixItem(); // for (int column = 1; column < matrixItems.length - 1; column += 2) { // for (int row = 1; row < matrixItems[column].length - 1; row += 2) { // pos_Medium = LDrawGridTypeT.getSnappedPos( // matrixItems[column][row].getCurrentPos(), // LDrawGridTypeT.Medium); // pos_Fine = LDrawGridTypeT.getSnappedPos( // matrixItems[column][row].getCurrentPos(), // LDrawGridTypeT.Fine); // // fineCoordinateMap = coordinateMap.get(pos_Medium); // if (fineCoordinateMap == null) // continue; // if (fineCoordinateMap.containsKey(pos_Fine) == false) // continue; // // for (MatrixItem eItem : fineCoordinateMap.get(pos_Fine)) { // if (partList // .contains(eItem.getParent().getParent())) // continue; // // if (matrixItems[column][row].isConnectable(eItem) == // ConnectivityTestResultT.True) { // if (eItem.getDirection() != Direction6T.Y_Minus) // continue; // if (conn instanceof Stud) { // if (lowestPos < matrixItems[column][row] // .getCurrentPos().y + 0.5f) // lowestPos = matrixItems[column][row] // .getCurrentPos().y + 0.5f; // } else { // if (lowestPos < matrixItems[column][row] // .getCurrentPos().y) // lowestPos = matrixItems[column][row] // .getCurrentPos().y; // } // break; // } // } // } // } // // } else { // pos_Medium = LDrawGridTypeT.getSnappedPos(conn.getCurrentPos(), // LDrawGridTypeT.Medium); // pos_Fine = LDrawGridTypeT.getSnappedPos(conn.getCurrentPos(), // LDrawGridTypeT.Fine); // // ConcurrentHashMap<Vector3f, ArrayList<Connectivity>> fineConnectivityMap // = connectivityCoordinateMap // .get(pos_Medium); // if (fineConnectivityMap == null) // continue; // ArrayList<Connectivity> eConnList = fineConnectivityMap // .get(pos_Fine); // if (eConnList == null) // continue; // // for (Connectivity eItem : eConnList) { // if (partList.contains(eItem.getParent())) // continue; // // if (conn.isConnectable(eItem) == ConnectivityTestResultT.True) { // if (lowestPos < conn.getCurrentPos().y) // lowestPos = conn.getCurrentPos().y; // } // } // } // } // // return lowestPos; // } public ArrayList<ConnectionPoint> getConnectionPoints(LDrawPart part) { ArrayList<ConnectionPoint> retList = new ArrayList<ConnectionPoint>(); if (part.getConnectivityMatrixItemList() != null) for (MatrixItem matrixItem : part.getConnectivityMatrixItemList()) { if (matrixItem.getConnectedConnectivity() != null) { if (matrixItem.isConnectable(matrixItem .getConnectedConnectivity()) == ConnectivityTestResultT.True) { ConnectionPoint point = new ConnectionPoint(matrixItem .getConnectedConnectivity().getParent() .getParent(), matrixItem, matrixItem.getConnectedConnectivity()); if (retList.contains(point) == false) retList.add(point); } } } for (Connectivity conn : part.getConnectivityList()) { if (conn.getConnectedConnectivity() == null) continue; for (Connectivity eItem : conn.getConnectedConnectivity()) { if (conn instanceof ICustom2DField == false && eItem instanceof ICustom2DField == false) { if (conn.isConnectable(eItem) == ConnectivityTestResultT.True) { ConnectionPoint point = new ConnectionPoint( eItem.getParent(), conn, eItem); if (retList.contains(point) == false) retList.add(point); } } } } return retList; } public boolean isRotatibleByCustom2dConn(LDrawPart part, ArrayList<MatrixItem> retRotationCenterList) { ArrayList<MatrixItem> connectingItemList = new ArrayList<MatrixItem>(); for (ConnectionPoint point : getConnectionPoints(part)) { if (point.getFrom() instanceof MatrixItem) connectingItemList.add((MatrixItem) (point.getFrom())); } if (connectingItemList.size() == 0) return false; ArrayList<MatrixItem> victimList = new ArrayList<MatrixItem>(); for (int i = 0; i < connectingItemList.size() - 1; i++) { for (int j = i + 1; j < connectingItemList.size(); j++) { Vector3f testVector = connectingItemList.get(i).getCurrentPos() .sub(connectingItemList.get(j).getCurrentPos()); if (Math.abs(Math.abs(testVector.dot(connectingItemList.get(i) .getDirectionVector())) - testVector.length()) <= 1.0f) { victimList.add(connectingItemList.get(i)); } } } connectingItemList.removeAll(victimList); HashMap<MatrixItem, ArrayList<LDrawPart>> connectedGroupMap = new HashMap<MatrixItem, ArrayList<LDrawPart>>(); for (MatrixItem item : connectingItemList) { connectedGroupMap.put(item, getConnectedPartBy(part, item)); } HashMap<MatrixItem, Boolean> isRotationalMap = new HashMap<MatrixItem, Boolean>(); for (int i = 0; i < connectingItemList.size() - 1; i++) { boolean isRotatable = true; if (isRotationalMap.containsKey(connectingItemList.get(i))) continue; for (int j = i; j < connectingItemList.size(); j++) { if (i == j) continue; for (LDrawPart tempPart : connectedGroupMap .get(connectingItemList.get(i))) { if (connectedGroupMap.get(connectingItemList.get(j)) .contains(tempPart)) { isRotatable = false; isRotationalMap.put(connectingItemList.get(i), false); isRotationalMap.put(connectingItemList.get(j), false); } break; } if (isRotatable == false) break; } } for (MatrixItem item : connectingItemList) { if (isRotationalMap.containsKey(item) == false) retRotationCenterList.add(item); } if (retRotationCenterList.size() == 0) return false; return true; // if (connectingItemList.size() == 1) // isRotatible = true; // else if (connectingItemList.size() == 2) { // MatrixItem item0 = connectingItemList.get(0); // MatrixItem item1 = connectingItemList.get(1); // // System.out.println(item0.getCurrentPos()); // // System.out.println(item1.getCurrentPos()); // // // System.out.println(item0.getCurrentPos().sub(item1.getCurrentPos()) // // .cross(item0.getDirectionVector()).length()); // // if (item0.getDirectionVector().equals(item1.getDirectionVector()) // || item0.getDirectionVector().equals( // item1.getDirectionVector().scale(-1))) { // if (MatrixMath.compareFloat( // item0.getCurrentPos().sub(item1.getCurrentPos()) // .cross(item0.getDirectionVector()).length(), // 0.1f) < 0) // isRotatible = true; // } // } // // System.out.println(connectingItemList.size()); // // System.out.println(isRotatible); // // if (rotationCenter != null && isRotatible == true) // rotationCenter.addAll(connectingItemList); // return isRotatible; } public ArrayList<Vector3f> getTestibleSnappedPos(Vector3f originalPos, LDrawGridTypeT unit) { ArrayList<Vector3f> retList = new ArrayList<Vector3f>(); Vector3f newPos; for (int x = Math.round(originalPos.x - unit.getXZValue() / 2); x <= Math .round(originalPos.x + unit.getXZValue() / 2); x += unit .getXZValue()) for (int y = Math.round(originalPos.y - unit.getYValue() / 2); y <= Math .round(originalPos.y + unit.getYValue() / 2); y += unit .getYValue()) for (int z = Math.round(originalPos.z - unit.getXZValue() / 2); z <= Math .round(originalPos.z + unit.getXZValue() / 2); z += unit .getXZValue()) { newPos = LDrawGridTypeT.getSnappedPos( new Vector3f(x, y, z), unit); if (retList.contains(newPos) == false) retList.add(newPos); } return retList; } }