/** * */ package org.goko.core.gcode.rs274ngcv3.modifier.rotate; import java.math.BigDecimal; import javax.vecmath.Matrix3d; import javax.vecmath.Point3d; import javax.vecmath.Tuple3d; import javax.vecmath.Vector3d; import org.goko.core.common.exception.GkException; import org.goko.core.common.exception.GkFunctionalException; import org.goko.core.common.exception.GkTechnicalException; import org.goko.core.common.measure.quantity.Angle; import org.goko.core.common.measure.quantity.AngleUnit; import org.goko.core.common.measure.quantity.Length; import org.goko.core.common.measure.units.Unit; import org.goko.core.controller.bean.EnumControllerAxis; import org.goko.core.gcode.element.GCodeLine; import org.goko.core.gcode.element.IGCodeProvider; import org.goko.core.gcode.element.IInstructionSetIterator; import org.goko.core.gcode.rs274ngcv3.context.GCodeContext; import org.goko.core.gcode.rs274ngcv3.element.GCodeProvider; import org.goko.core.gcode.rs274ngcv3.element.IModifier; import org.goko.core.gcode.rs274ngcv3.element.InstructionProvider; import org.goko.core.gcode.rs274ngcv3.element.InstructionType; import org.goko.core.gcode.rs274ngcv3.instruction.AbstractInstruction; import org.goko.core.gcode.rs274ngcv3.instruction.AbstractStraightInstruction; import org.goko.core.gcode.rs274ngcv3.instruction.ArcFeedInstruction; import org.goko.core.gcode.rs274ngcv3.modifier.AbstractModifier; import org.goko.core.gcode.rs274ngcv3.utils.InstructionUtils; import org.goko.core.math.Arc3b; import org.goko.core.math.Tuple6b; /** * @author Psyko * @date 11 mai 2016 */ public class RotateModifier extends AbstractModifier<GCodeProvider> implements IModifier<GCodeProvider>{ /** The rotation angle */ private Angle rotationAngle = Angle.valueOf("45", AngleUnit.DEGREE_ANGLE); /** The rotation axis */ private EnumControllerAxis rotationAxis = EnumControllerAxis.Z_POSITIVE; /** Rotation matrix */ private Matrix3d rotationMatrix; /** * Constructeur */ public RotateModifier() { super("Rotate"); } // fix wrap and autolevel modifier ? /** (inheritDoc) * @see org.goko.core.gcode.rs274ngcv3.element.IModifier#isConfigured() */ @Override public boolean isConfigured() { return rotationAngle != null; } /** (inheritDoc) * @see org.goko.core.gcode.rs274ngcv3.modifier.AbstractModifier#applyModifier(org.goko.core.gcode.element.IGCodeProvider, org.goko.core.gcode.rs274ngcv3.element.GCodeProvider) */ @Override protected void applyModifier(IGCodeProvider source, GCodeProvider target) throws GkException { rotationMatrix = null; GCodeContext localContext = new GCodeContext(); InstructionProvider sourceInstructionSet = getRS274NGCService().getInstructions(localContext, source); IInstructionSetIterator<GCodeContext, AbstractInstruction> iterator = getRS274NGCService().getIterator(sourceInstructionSet, localContext); while(iterator.hasNext()){ GCodeContext preContext = iterator.getContext(); AbstractInstruction instr = iterator.next(); if(instr.getType() == InstructionType.STRAIGHT_FEED || instr.getType() == InstructionType.STRAIGHT_TRAVERSE){ AbstractStraightInstruction straightInstruction = (AbstractStraightInstruction) instr; rotateStraightInstruction((AbstractStraightInstruction)straightInstruction, preContext); }else if(instr.getType() == InstructionType.ARC_FEED){ rotateArcInstruction((ArcFeedInstruction)instr, preContext); } } GCodeProvider result = getRS274NGCService().getGCodeProvider(localContext, sourceInstructionSet); for (GCodeLine line : result.getLines()) { target.addLine(line); } } /** * @param straightInstruction * @param preContext */ private void rotateStraightInstruction(AbstractStraightInstruction instr, GCodeContext preContext) throws GkException{ Unit<Length> unit = preContext.getUnit().getUnit(); GCodeContext postContext = new GCodeContext(preContext); instr.apply(postContext); Tuple6b tuple = postContext.getPosition(); Vector3d tuple3d = tuple.toVector3d(unit); rotate(tuple3d); instr.setX( Length.valueOf(BigDecimal.valueOf(tuple3d.x), unit)); instr.setY( Length.valueOf(BigDecimal.valueOf(tuple3d.y), unit)); instr.setZ( Length.valueOf(BigDecimal.valueOf(tuple3d.z), unit)); } private void calculateRotationMatrix() throws GkException{ if(rotationMatrix == null){ rotationMatrix = new Matrix3d(); rotationMatrix.setIdentity(); switch(rotationAxis){ case X_POSITIVE: rotationMatrix.rotX(rotationAngle.doubleValue(AngleUnit.RADIAN)); break; case Y_POSITIVE: rotationMatrix.rotY(rotationAngle.doubleValue(AngleUnit.RADIAN)); break; case Z_POSITIVE: rotationMatrix.rotZ(rotationAngle.doubleValue(AngleUnit.RADIAN)); break; default: throw new GkTechnicalException("Unsupported rotation axis "+rotationAxis.getCode()); } } } private void rotate(Tuple3d tuple3d) throws GkException{ calculateRotationMatrix(); rotationMatrix.transform(tuple3d); } private void checkRotationPlane(GCodeContext preContext) throws GkException { switch(preContext.getPlane()){ case XY_PLANE: if(rotationAxis != EnumControllerAxis.Z_POSITIVE){ throw new GkFunctionalException("An arc motion in the XY plane can only be rotated around Z"); } break; case YZ_PLANE: if(rotationAxis != EnumControllerAxis.X_POSITIVE){ throw new GkFunctionalException("An arc motion in the YZ plane can only be rotated around X"); } break; case XZ_PLANE: if(rotationAxis != EnumControllerAxis.Y_POSITIVE){ throw new GkFunctionalException("An arc motion in the XZ plane can only be rotated around Y"); } break; default: throw new GkTechnicalException("Not supported "+preContext.getPlane()); } } private void rotateArcInstruction(ArcFeedInstruction instr, GCodeContext preContext) throws GkException { // Make sure the arc is in a plane that can be rotated checkRotationPlane(preContext); Arc3b arc = InstructionUtils.getArc(preContext, instr); Unit<Length> unit = preContext.getUnit().getUnit(); Point3d start = arc.getStart().toPoint3d(unit); Point3d end = arc.getEnd().toPoint3d(unit); Point3d center = arc.getCenter().toPoint3d(unit); rotate(start); rotate(end); rotate(center); //pas bon switch(preContext.getDistanceMode()){ case ABSOLUTE: instr.setX(Length.valueOf(BigDecimal.valueOf(end.x), unit)); instr.setY(Length.valueOf(BigDecimal.valueOf(end.y), unit)); instr.setZ(Length.valueOf(BigDecimal.valueOf(end.z), unit)); break; case RELATIVE: instr.setX(Length.valueOf(BigDecimal.valueOf(end.x - start.x), unit)); instr.setY(Length.valueOf(BigDecimal.valueOf(end.y - start.y), unit)); instr.setZ(Length.valueOf(BigDecimal.valueOf(end.z - start.z), unit)); break; default: throw new GkTechnicalException("Not supported "+preContext.getDistanceMode()); } instr.setI(Length.valueOf(BigDecimal.valueOf(center.x - start.x), unit)); instr.setJ(Length.valueOf(BigDecimal.valueOf(center.y - start.y), unit)); instr.setK(Length.valueOf(BigDecimal.valueOf(center.z - start.z), unit)); // // switch(preContext.getPlane()){ // case XY_PLANE: // instr.setFirstEnd(Length.valueOf(BigDecimal.valueOf(end.x), unit)); // instr.setSecondEnd(Length.valueOf(BigDecimal.valueOf(end.y), unit)); // instr.setFirstAxis(Length.valueOf(BigDecimal.valueOf(center.x), unit)); // instr.setSecondAxis(Length.valueOf(BigDecimal.valueOf(center.y), unit)); // instr.setAxisEndPoint(Length.valueOf(BigDecimal.valueOf(end.z), unit)); // break; // case YZ_PLANE: // instr.setFirstEnd(Length.valueOf(BigDecimal.valueOf(end.y), unit)); // instr.setSecondEnd(Length.valueOf(BigDecimal.valueOf(end.z), unit)); // instr.setFirstAxis(Length.valueOf(BigDecimal.valueOf(center.y), unit)); // instr.setSecondAxis(Length.valueOf(BigDecimal.valueOf(center.z), unit)); // instr.setAxisEndPoint(Length.valueOf(BigDecimal.valueOf(end.x), unit)); // break; // case XZ_PLANE: // instr.setFirstEnd(Length.valueOf(BigDecimal.valueOf(end.z), unit)); // instr.setSecondEnd(Length.valueOf(BigDecimal.valueOf(end.x), unit)); // instr.setFirstAxis(Length.valueOf(BigDecimal.valueOf(center.z), unit)); // instr.setSecondAxis(Length.valueOf(BigDecimal.valueOf(center.x), unit)); // instr.setAxisEndPoint(Length.valueOf(BigDecimal.valueOf(end.y), unit)); // break; // default: throw new GkTechnicalException("Not supported "+preContext.getPlane()); // } } /** * @return the rotationAngle */ public Angle getRotationAngle() { return rotationAngle; } /** * @param rotationAngle the rotationAngle to set */ public void setRotationAngle(Angle rotationAngle) { this.rotationAngle = rotationAngle; } /** * @return the rotationAxis */ public EnumControllerAxis getRotationAxis() { return rotationAxis; } /** * @param rotationAxis the rotationAxis to set */ public void setRotationAxis(EnumControllerAxis rotationAxis) { this.rotationAxis = rotationAxis; } }