public static Placement createPlacement( String id, String partId, double x, double y, double z, double rotation, Side side) { Placement placement = new Placement(id); placement.setPart(Configuration.get().getPart(partId)); placement.setLocation(new Location(LengthUnit.Millimeters, x, y, z, rotation)); placement.setSide(side); return placement; }
private boolean step4() { placementB = jobPanel.getSelectedPlacement(); if (placementB == null || placementB == placementA) { MessageBoxes.errorBox(mainFrame, "Error", "Please select a second placement."); return false; } if (placementA.getSide() != placementB.getSide()) { MessageBoxes.errorBox( mainFrame, "Error", "Both placements must be on the same side of the board."); return false; } // Get the Locations we'll be using and convert to system units. Location boardLocationA = placementLocationA.convertToUnits(Configuration.get().getSystemUnits()); Location placementLocationA = placementA.getLocation().convertToUnits(Configuration.get().getSystemUnits()); Location boardLocationB = placementLocationB.convertToUnits(Configuration.get().getSystemUnits()); Location placementLocationB = placementB.getLocation().convertToUnits(Configuration.get().getSystemUnits()); // If the placements are on the Bottom of the board we need to invert X if (placementA.getSide() == Side.Bottom) { // boardLocationA = boardLocationA.invert(true, false, false, false); placementLocationA = placementLocationA.invert(true, false, false, false); // boardLocationB = boardLocationB.invert(true, false, false, false); placementLocationB = placementLocationB.invert(true, false, false, false); } logger.debug(String.format("locate")); logger.debug(String.format("%s - %s", boardLocationA, placementLocationA)); logger.debug(String.format("%s - %s", boardLocationB, placementLocationB)); double x1 = placementLocationA.getX(); double y1 = placementLocationA.getY(); double x2 = placementLocationB.getX(); double y2 = placementLocationB.getY(); // Calculate the expected angle between the two coordinates, based // on their locations in the placement. double expectedAngle = Math.atan2(y1 - y2, x1 - x2); expectedAngle = Math.toDegrees(expectedAngle); logger.debug("expectedAngle " + expectedAngle); // Then calculate the actual angle between the two coordinates, // based on the captured values. x1 = boardLocationA.getX(); y1 = boardLocationA.getY(); x2 = boardLocationB.getX(); y2 = boardLocationB.getY(); double indicatedAngle = Math.atan2(y1 - y2, x1 - x2); indicatedAngle = Math.toDegrees(indicatedAngle); logger.debug("indicatedAngle " + indicatedAngle); // Subtract the difference and we have the angle that the board // is rotated by. double angle = indicatedAngle - expectedAngle; logger.debug("angle " + angle); // Now we want to derive the position of 0,0 in relation to the // two captured coordinates. We will use the intersection of two // circles centered at the coordinates with a radius of the // distance from each coordinate to 0,0. // Circle intersection solver borrowed from // http://www.vb-helper.com/howto_circle_circle_intersection.html // Get the two circles center points and radius. double cx0 = boardLocationA.getX(); double cy0 = boardLocationA.getY(); double radius0 = Math.sqrt(Math.pow(placementLocationA.getX(), 2) + Math.pow(placementLocationA.getY(), 2)); double cx1 = boardLocationB.getX(); double cy1 = boardLocationB.getY(); double radius1 = Math.sqrt(Math.pow(placementLocationB.getX(), 2) + Math.pow(placementLocationB.getY(), 2)); logger.debug(String.format("%f %f %f %f %f %f", cx0, cy0, radius0, cx1, cy1, radius1)); // Calculate the distance between the two center points. double dx = cx0 - cx1; double dy = cy0 - cy1; double dist = Math.sqrt(dx * dx + dy * dy); double a = (radius0 * radius0 - radius1 * radius1 + dist * dist) / (2 * dist); double h = Math.sqrt(radius0 * radius0 - a * a); double cx2 = cx0 + a * (cx1 - cx0) / dist; double cy2 = cy0 + a * (cy1 - cy0) / dist; double intersectionx1 = cx2 + h * (cy1 - cy0) / dist; double intersectiony1 = cy2 - h * (cx1 - cx0) / dist; double intersectionx2 = cx2 - h * (cy1 - cy0) / dist; double intersectiony2 = cy2 + h * (cx1 - cx0) / dist; // We now have the locations of the two intersecting points on // the circles. Now we have to figure out which one is correct. Point p0 = new Point(intersectionx1, intersectiony1); Point p1 = new Point(intersectionx2, intersectiony2); logger.debug(String.format("p0 = %s, p1 = %s", p0, p1)); // Create two points based on the boardLocationA. Point p0r = new Point(boardLocationA.getX(), boardLocationA.getY()); Point p1r = new Point(boardLocationA.getX(), boardLocationA.getY()); // Translate each point by one of the results from the circle // intersection p0r = Utils2D.translatePoint(p0r, p0.getX() * -1, p0.getY() * -1); p1r = Utils2D.translatePoint(p1r, p1.getX() * -1, p1.getY() * -1); // Rotate each point by the negative of the angle previously // calculated. This effectively de-rotates the point with one of the // results as the origin. p0r = Utils2D.rotatePoint(p0r, angle * -1); p1r = Utils2D.rotatePoint(p1r, angle * -1); logger.debug(String.format("p0r = %s, p1r = %s", p0r, p1r)); // Now, whichever result is closer to the value of boardLocationA // is the right result. So, calculate the linear distance between // the calculated point and the placementLocationA. double d0 = Math.abs( Math.sqrt( Math.pow(p0r.x - placementLocationA.getX(), 2) + Math.pow(p0r.y - placementLocationA.getY(), 2))); double d1 = Math.abs( Math.sqrt( Math.pow(p1r.x - placementLocationA.getX(), 2) + Math.pow(p1r.y - placementLocationA.getY(), 2))); logger.debug(String.format("d0 %f, d1 %f", d0, d1)); Point result = ((d0 < d1) ? p0 : p1); logger.debug("Result: " + result); Location boardLocation = new Location(Configuration.get().getSystemUnits(), result.x, result.y, 0, angle * -1); Location oldBoardLocation = jobPanel.getSelectedBoardLocation().getLocation(); oldBoardLocation = oldBoardLocation.convertToUnits(boardLocation.getUnits()); boardLocation = boardLocation.derive(null, null, oldBoardLocation.getZ(), null); jobPanel.getSelectedBoardLocation().setLocation(boardLocation); jobPanel.refreshSelectedBoardRow(); return true; }