public virtual void Reset(bool shouldResetView = true) { // reset extents MinX = double.MaxValue; MaxX = double.MinValue; MinY = double.MaxValue; MaxY = double.MinValue; // update counter Count = 0; // reset buffers with defaults _lines = new List <VertexGroup>() { new VertexGroup(DefaultLineColor) }; _points = new List <VertexGroup>() { new VertexGroup(DefaultPointColor) }; _openPolylines = new List <VertexGroup>(); _closedPolylines = new List <VertexGroup>(); // reset mouse position Mouse = new MVertex(); if (shouldResetView) { ResetView(); } }
private double GetAngle(MVertex v1, MVertex v2) { return(Math.Atan2( v2.Y - v1.Y, v2.X - v1.X )); }
public AlignmentCalculationWrapper( MVertex invertsIn, MVertex c2bOffsetsIn, MVertex fiducialAIn, MVertex fiducialStageAIn, MVertex fiducialBIn, MVertex fiducialStageBIn ) { // update the inverts Inverts = invertsIn; // update the camera to beam offsets C2BOffsets = c2bOffsetsIn; // update the CAD fiducials FiducialA_CAD = fiducialAIn; FiducialB_CAD = fiducialBIn; // update the stage fiducials FiducialA_Stage = fiducialStageAIn; FiducialB_Stage = fiducialStageBIn; Update(); }
private static MVertex Average(MVertex aIn, MVertex bIn) { return(new MVertex( (aIn.X + bIn.X) / 2d, (aIn.Y + bIn.Y) / 2d )); }
private static MVertex Sum(MVertex aIn, MVertex bIn) { return(new MVertex( (aIn.X + bIn.X), (aIn.Y + bIn.Y) )); }
/// <summary> /// Calculates the target (as per CAD) on the stage centred about the /// optical axis. The stage will have limited travel, and may not be /// able to reach the target coordinate. In this case, move the mask /// stage as close as possible to the target coordinate. /// The remaining distance to the target is applied as a SCANNER OFFSET. /// </summary> /// <param name="targetOnCADIn">The target position as per CAD</param> /// <param name="stageLimitsIn">The maximum and minimum stage boundaries</param> /// <param name="scannerLimitsIn">The maximum and minimum scanner boundaries</param> /// <returns>The actual stage coordinate and scanner offsets</returns> public (MVertex StagePosition, MVertex ScannerOffsets, bool IsWithinBounds) GetTargetPositionOnStage(MVertex targetOnCADIn, MLimit stageLimitsIn, MLimit scannerLimitsIn) { bool isWithinBounds = true; // calculate the position on the stage MVertex targetOnStage = GetTargetPositionOnStage(targetOnCADIn); // constrain the position to the stage's limits var constrainedStagePosition = new MVertex( Constrain(targetOnStage.X, stageLimitsIn.MinimumX, stageLimitsIn.MaximumX), Constrain(targetOnStage.Y, stageLimitsIn.MinimumY, stageLimitsIn.MaximumY) ); // apply remaining offsets to the scanner var scannerOffsets = new MVertex( -1 * (targetOnStage.X - constrainedStagePosition.X), -1 * (targetOnStage.Y - constrainedStagePosition.Y) ); // ensure scanner offsets are within the scanner's limits if ( scannerOffsets.X < scannerLimitsIn.MinimumX || scannerOffsets.X > scannerLimitsIn.MaximumX || scannerOffsets.Y < scannerLimitsIn.MinimumY || scannerOffsets.Y > scannerLimitsIn.MaximumY ) { isWithinBounds = false; } return(constrainedStagePosition, scannerOffsets, isWithinBounds); }
/// <summary> /// Calculates the target (as per CAD) on the stage centred about the /// optical axis. /// </summary> /// <param name="stageOriginIn">The stage origin from a previous calculated result</param> /// <param name="targetOnCADIn">The target position as per CAD</param> /// <param name="stageAngleIn">The angle from a previously calculated result</param> /// <returns>The actual stage coordinate</returns> public static MVertex GetTargetPositionOnStage(MVertex invertsIn, MarkGeometryPoint targetOnCADIn, MVertex stageOriginIn, double stageAngleIn) { return(new MVertex( (stageOriginIn.X + (invertsIn.X * (((targetOnCADIn.X) * Math.Cos(stageAngleIn)) - ((targetOnCADIn.Y) * Math.Sin(stageAngleIn))))), (stageOriginIn.Y + (invertsIn.Y * (((targetOnCADIn.X) * Math.Sin(stageAngleIn)) + ((targetOnCADIn.Y) * Math.Cos(stageAngleIn))))) )); }
/// <summary> /// Calculates the target (as per CAD) on the stage centred about the /// optical axis. /// </summary> /// <param name="stageOriginIn">The stage origin from a previous calculated result</param> /// <param name="targetOnCADIn">The target position as per CAD</param> /// <param name="stageAngleIn">The angle from a previously calculated result</param> /// <returns>The actual stage coordinate</returns> public MVertex GetTargetPositionOnStage(MVertex targetOnCADIn, MVertex stageOriginIn, double stageAngleIn) { return(new MVertex( (stageOriginIn.X + (Inverts.X * (((targetOnCADIn.X) * Math.Cos(stageAngleIn)) - ((targetOnCADIn.Y) * Math.Sin(stageAngleIn))))), (stageOriginIn.Y + (Inverts.Y * (((targetOnCADIn.X) * Math.Sin(stageAngleIn)) + ((targetOnCADIn.Y) * Math.Cos(stageAngleIn))))) )); }
public virtual void ZoomToFit(MVertex centrePoint, double width, double height) { double newScale = _reservedViewPortSize / Math.Max(width, height); _panOffset.X = -newScale * (centrePoint.X + _cadOffset.X); _panOffset.Y = -newScale * (centrePoint.Y + _cadOffset.Y); _zoom = newScale / _scale; Render(); }
} // pointer to e1 (forward) and e2 (backward) edges public static LinkedList <IntersectionStructure> Create(MVertex intersectionPoint, STLEdge forwardEdge, STLEdge backwardEdge) { var iis = new LinkedList <IntersectionStructure>(); iis.AddLast( new IntersectionStructure() { ForwardEdgeIntersectionPoint = intersectionPoint, ForwardEdge = forwardEdge, BackwardEdge = backwardEdge } ); return(iis); }
// TODO: Implement mask angle align func // 1. The mask angle is measured directly by camera. // 2. The mask is rotated to compensate for the angle. // 3. The procedure continues until the angle is zero. public MVertex ConvertCADToMachineCoordinate(MVertex cadOrigin, MVertex pointOnCAD) { var transform = GeometricArithmeticModule.CombineTransformations( GeometricArithmeticModule.GetTranslationTransformationMatrix( -cadOrigin.X, -cadOrigin.Y ), GeometricArithmeticModule.GetRotationTransformationMatrix( 0, 0, Angle ), GeometricArithmeticModule.GetTranslationTransformationMatrix( OriginRelativeBEAM.X, OriginRelativeBEAM.Y ) ); var result = Vector3.Transform( new Vector3((float)pointOnCAD.X, (float)pointOnCAD.Y, 0), transform ); return(new MVertex(Inverts.X * result.X, Inverts.Y * result.Y)); }
public void Update() { // calculate the expected angle in radians // Note: Atan2 is Y / X ExpectedAngle = Math.Atan2( FiducialB_CAD.Y - FiducialA_CAD.Y, FiducialB_CAD.X - FiducialA_CAD.X ); // add the target angle to the expected angle ExpectedAngle += TargetAngle; // calculate the actual angle in radians // Note: Atan2 is Y / X ActualAngle = Math.Atan2( (Inverts.Y * FiducialB_Stage.Y) - (Inverts.Y * FiducialA_Stage.Y), (Inverts.X * FiducialB_Stage.X) - (Inverts.X * FiducialA_Stage.X) ); // calculate the angle in radians Angle = ActualAngle - ExpectedAngle; // calculate the position based on fiducial A (rel to camera) PositionRelativeFidA = new MVertex( FiducialA_Stage.X - (Inverts.X * ((FiducialA_CAD.X * Math.Cos(Angle)) - (FiducialA_CAD.Y * Math.Sin(Angle)))), FiducialA_Stage.Y - (Inverts.Y * ((FiducialA_CAD.X * Math.Sin(Angle)) + (FiducialA_CAD.Y * Math.Cos(Angle)))) ); // calculate the position based on fiducial A (rel to camera) PositionRelativeFidB = new MVertex( FiducialB_Stage.X - (Inverts.X * ((FiducialB_CAD.X * Math.Cos(Angle)) - (FiducialB_CAD.Y * Math.Sin(Angle)))), FiducialB_Stage.Y - (Inverts.Y * ((FiducialB_CAD.X * Math.Sin(Angle)) + (FiducialB_CAD.Y * Math.Cos(Angle)))) ); // calculate the origin (rel to camera) OriginRelativeCAM = Average(PositionRelativeFidA, PositionRelativeFidB); // calculate the origin (rel to beam) OriginRelativeBEAM = Sum(OriginRelativeCAM, C2BOffsets); }
private MarkGeometryPoint ToPoint(MVertex vIn) { return(new MarkGeometryPoint(vIn.X, vIn.Y)); }
public List <MarkGeometryPoint> ToPoints(double deviationToleranceDeg = 1) { if (IntersectionList.Count <= 0) { return(new List <MarkGeometryPoint>()); } else if (IntersectionList.Count <= 1) { return new List <MarkGeometryPoint> { ToPoint(IntersectionList.First.Value.ForwardEdgeIntersectionPoint) } } ; MVertex previousPoint = null; var lastEntry = IntersectionList.First; var points = new List <MarkGeometryPoint> { ToPoint(lastEntry.Value.ForwardEdgeIntersectionPoint) }; var current = lastEntry.Next; double referenceAngle = GetAngle( lastEntry.Value.ForwardEdgeIntersectionPoint, current.Value.ForwardEdgeIntersectionPoint ); deviationToleranceDeg = GeometricArithmeticModule.ToRadians(deviationToleranceDeg); while (current != null) { var angle = GetAngle( lastEntry.Value.ForwardEdgeIntersectionPoint, current.Value.ForwardEdgeIntersectionPoint ); if (Math.Abs(referenceAngle - angle) > deviationToleranceDeg) { lastEntry = current.Previous; points.Add(ToPoint(lastEntry.Value.ForwardEdgeIntersectionPoint)); referenceAngle = GetAngle( lastEntry.Value.ForwardEdgeIntersectionPoint, current.Value.ForwardEdgeIntersectionPoint ); } previousPoint = current.Value.ForwardEdgeIntersectionPoint; current = current.Next; } if (previousPoint != null) { points.Add(ToPoint(previousPoint)); } // close contour if closed, i.e. first edge touches last edge if (MSTLSlicer.CompareEqual(IntersectionList.First.Value.ForwardEdge, IntersectionList.Last.Value.BackwardEdge)) { points.Add(new MarkGeometryPoint(IntersectionList.First.Value.ForwardEdgeIntersectionPoint.X, IntersectionList.First.Value.ForwardEdgeIntersectionPoint.Y)); } return(points); }
/// <summary> /// Calculates the target (as per CAD) on the stage centred about the /// optical axis. /// </summary> /// <param name="targetOnCADIn">The target position as per CAD</param> /// <returns>The actual stage coordinate</returns> public MVertex GetTargetPositionOnStage(MVertex targetOnCADIn) { return(GetTargetPositionOnStage(targetOnCADIn, OriginRelativeBEAM, Angle)); }