/// <summary> /// Read DRL data replacing the drill positions with a custom pattern /// </summary> /// <param name="pattern">A pattern relative to it's origin 0,0</param> /// <param name="howmany">The number of elements to read</param> /// <returns>A list of geometries</returns> public List <IMarkGeometry> ReadAndReplaceWithCustom(List <IMarkGeometry> pattern, long howmany = -1) { var buffer = new List <IMarkGeometry>(); BeginGetAll( (data) => { if (data.Geometry is MarkGeometryPoint point) { var transform = GeometricArithmeticModule.GetTranslationTransformationMatrix(point); for (int i = 0; i < pattern.Count; i++) { var clone = (IMarkGeometry)pattern[i].Clone(); clone.Transform(transform); buffer.Add(clone); } } else { buffer.Add(data.Geometry); } }, howmany ); return(buffer); }
/// <summary> /// Use method to invert an input transform matrix about a given origin. /// Could help when combining transformation for stages with inverted axis. /// </summary> /// <param name="taskHandler">An implementation of the process configuration tasks</param> /// <param name="parentTransform">The parent transform in the chain of transformations</param> /// <param name="transform">The input transformation</param> /// <param name="ctIn">A cancellation token</param> /// <returns>The input matrix flip about it's parent's transform</returns> public async Task <Matrix4x4> InvertTransform(IProcessConfigurationTasksHandler taskHandler, Matrix4x4 parentTransform, Matrix4x4 transform, CancellationToken ctIn) { var origin = new MarkGeometryPoint(); origin.Transform(parentTransform); var inverts = await taskHandler.GetStageInverts(ctIn); return(GeometricArithmeticModule.CombineTransformations( // flip about the base transform's origin GeometricArithmeticModule.GetTranslationTransformationMatrix( -origin.X, -origin.Y, -origin.Z ), // apply the next transform transform, // flip the next transform on the requested x-axis GeometricArithmeticModule.GetScalingTransformationMatrix( inverts.InvertX ? -1 : 1, inverts.InvertY ? -1 : 1 ), // translate back to the base transform's origin GeometricArithmeticModule.GetTranslationTransformationMatrix( origin.X, origin.Y, origin.Z ) )); }
public static Matrix4x4 GetAlignmentTransform(MAlignmentType alignmentType, List <MarkGeometryPoint> estimatedPoints, List <MarkGeometryPoint> measuredPoints) { if (alignmentType == MAlignmentType.Type1 && measuredPoints?.Count > 0) { return(GeometricArithmeticModule.GetTranslationTransformationMatrix( measuredPoints[0].X, measuredPoints[0].Y )); } return(GeometricArithmeticModule.EstimateTransformationMatrixFromPoints( estimatedPoints, measuredPoints )); }
public virtual void AddRecipeNode(MRecipe recipe, MRecipeBaseNode recipeNode) { if (recipe == null || recipeNode == null) { return; } var extents = GeometryExtents <double> .CreateDefaultDouble(); MRecipe.BeginGetAllLayers_Parallel(recipeNode, (layer) => { extents = GeometryExtents <double> .Combine( extents, AddLayer(recipe, layer) ); }); // calculate size of fiducial relative to the node var fiducialSize = 0.025 * extents.Hypotenuse; // generate fiducial pattern GenerateFiducialPattern(fiducialSize); // get node's transform var parentsTransform = (recipeNode.Parent as MRecipeBaseNode)?.TransformInfo.ToMatrix4x4() ?? GeometricArithmeticModule.GetDefaultTransformationMatrix(); // render fiducials in parent's reference frame foreach (var fiducial in recipeNode.Fiducials) { var transform = GeometricArithmeticModule.CombineTransformations( GeometricArithmeticModule.GetTranslationTransformationMatrix( fiducial.X, fiducial.Y, fiducial.Z ), parentsTransform ); foreach (var geometry in _fiducialPattern) { var clone = (IMarkGeometry)geometry.Clone(); clone.Transform(transform); AddDefault(clone, FiducialColor); } } }
public Matrix4x4 ToMatrix4x4() { return(GeometricArithmeticModule.CombineTransformations( // apply scale GeometricArithmeticModule.GetScalingTransformationMatrix( ScaleX, ScaleY, ScaleZ ), // apply rotation - don't forget to convert degrees to radians GeometricArithmeticModule.GetRotationTransformationMatrix( GeometricArithmeticModule.ToRadians(RotationDegX), GeometricArithmeticModule.ToRadians(RotationDegY), GeometricArithmeticModule.ToRadians(RotationDegZ) ), // apply offset GeometricArithmeticModule.GetTranslationTransformationMatrix( OffsetX, OffsetY, OffsetZ ) )); }
// 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 bool SaveImage(string filePath) { var bitmap = new Bitmap( 480, 480, PixelFormat.Format24bppRgb ); var shader = new GeometryShader2D(); shader.UpdateSettings(1, 1, Color.Red, Color.Green, Color.Transparent); shader.Reset(bitmap, Color.Black); var xScale = bitmap.Width / Boundary.Extents.Width; var yScale = bitmap.Height / Boundary.Extents.Height; // calculate transform var transformationMatrix = GeometricArithmeticModule.CombineTransformations( // centre geometries at origin before scaling GeometricArithmeticModule.GetTranslationTransformationMatrix( -Boundary.Extents.Centre.X, -Boundary.Extents.Centre.Y ), // scale geometries to fit the target bitmap GeometricArithmeticModule.GetScalingTransformationMatrix( xScale, -yScale ), // centre geometries in target bitmap GeometricArithmeticModule.GetTranslationTransformationMatrix( 0.5 * bitmap.Width, 0.5 * bitmap.Height ) ); Draw(bitmap, shader, transformationMatrix); return(shader.WriteToFile(bitmap, filePath, PixelFormat.Format24bppRgb, 120, 120, GeometryShader2D.OptimisationSetting.Default)); }
public async Task <Matrix4x4> GetAbsoluteTransformFromStageOrigin( IProcessConfigurationTasksHandler taskHandler, ICamToBeam cam2Beam, MRecipe recipe, MRecipeBaseNode recipeNode, CancellationToken ctIn ) { // firstly, find closest parent with fiducials var parent = recipeNode; while ( parent != null && parent.Fiducials.Count <= 0 ) { parent = parent.Parent as MRecipeBaseNode; } if (parent != null) { // recursion - get it's parent's transform var baseTransform = await GetAbsoluteTransformFromStageOrigin( taskHandler, cam2Beam, recipe, parent.Parent as MRecipeBaseNode, ctIn ); var fiducialPoints = new List <MarkGeometryPoint>(); var measuredPoints = new List <MarkGeometryPoint>(); for (int i = 0; i < parent.Fiducials.Count; i++) { var fiducial = parent.Fiducials[i]; if (!_cachedFiducials.ContainsKey(fiducial)) { // estimate stage position var stageLocation = new MarkGeometryPoint( fiducial.X, fiducial.Y, fiducial.Z ); stageLocation.Transform(baseTransform); // goto estimated position if (!await taskHandler.GotoXY( stageLocation.X, stageLocation.Y, ctIn )) { throw new Exception($"Failed to goto the estimated position; origin: {await taskHandler.GetStageOrigin(ctIn)}, fiducial: {(fiducial.X, fiducial.Y)} est: {stageLocation}"); } // find and centre { if (!await cam2Beam.MoveBeamToCamOffset(ctIn)) { throw new Exception($"Failed to move beam to cam offset"); } if (!await taskHandler.MovetoCameraFocus(ctIn)) { throw new Exception($"Failed to move camera to focus"); } await taskHandler.SwitchCameraLedOn(ctIn); // attempt to centre on fiducial if (!await taskHandler.CentreOnVisibleObject(ctIn)) { _logger.Info($"Failed to centre on fiducial"); // ask user to locate fiducials Application.Current.Dispatcher.Invoke( () => { var fidVm = taskHandler.GetNewFidFindViewModel(); var inspectionDialog = new InspectionWindow(fidVm, Application.Current.MainWindow); inspectionDialog.Owner = Application.Current.MainWindow; if (inspectionDialog.ShowDialog() != true) { throw new Exception("Failed to find fiducial"); } // TODO : think about updating the machine's origin } ); } if (!await cam2Beam.MoveCamToBeamOffset(ctIn)) { throw new Exception($"Failed to move camera to beam offset"); } } // read fiducial position var(stgX, stgY, success) = await taskHandler.GetStageXY(ctIn); if (!success) { throw new Exception("Failed to read the current stage position"); } // update cache _cachedFiducials[fiducial] = new MarkGeometryPoint(stgX, stgY); } // update measured points fiducialPoints.Add(new MarkGeometryPoint(fiducial.X, fiducial.Y)); measuredPoints.Add(_cachedFiducials[fiducial]); } // calculate transform from measured fiducials var parentTransform = GeometricArithmeticModule.EstimateTransformationMatrixFromPoints( fiducialPoints, measuredPoints ); return(GeometricArithmeticModule.CombineTransformations( parentTransform, await InvertTransform( taskHandler, parentTransform, MRecipe.GetRelativeTransformFromParent( parent, recipeNode ), ctIn ) )); } var origin = await taskHandler.GetStageOrigin(ctIn); var stageOrigin = GeometricArithmeticModule.GetTranslationTransformationMatrix( origin.X, origin.Y ); return(GeometricArithmeticModule.CombineTransformations( stageOrigin, await InvertTransform( taskHandler, stageOrigin, MRecipe.GetRelativeTransform( recipe, recipeNode ), ctIn ) )); }
public void Render() { _terminableTaskExecutor.CancelCurrentAndRun( (ctIn) => { // reset shader MShader.Reset(); if (_geometriesBuffer != null) { int count = 0; var extents = GeometryExtents <double> .CreateDefaultDouble(); foreach (var layerName in _geometriesBuffer.Keys) { MShader.AddDefault( _geometriesBuffer[layerName], _colours[(count++) % _colours.Length] ); extents = GeometryExtents <double> .Combine( extents, GeometricArithmeticModule.CalculateExtents(_geometriesBuffer[layerName]) ); } // overlay tiles foreach (var tile in MTileSettings.ToTiles(TileSettings, extents)) { MShader.AddDefault((MarkGeometryRectangle)tile, _tileColor); } // calculate size of fiducial relative to the node var fiducialSize = 0.05 * extents.Hypotenuse; // generate fiducial pattern GenerateFiducialPattern(fiducialSize); // get base transform var baseTransform = GeometricArithmeticModule.GetTranslationTransformationMatrix( extents.Centre.X, extents.Centre.Y ); // render fiducials in parent's reference frame foreach (var fiducial in Fiducials) { var transform = GeometricArithmeticModule.CombineTransformations( baseTransform, GeometricArithmeticModule.GetTranslationTransformationMatrix( fiducial.X, fiducial.Y, fiducial.Z ) ); foreach (var geometry in _fiducialPattern) { var clone = (IMarkGeometry)geometry.Clone(); clone.Transform(transform); MShader.AddDefault(clone, _fiducialColor); } } } // stop if new render is requested ctIn.ThrowIfCancellationRequested(); MShader.Render(); DrawingExtentsX = MShader.Width; DrawingExtentsY = MShader.Height; DrawingCount = MShader.Count; } ); }
public void Render() { _terminableTaskExecutor.CancelCurrentAndRun( (ctIn) => { // reset shader MShader.Reset(); if (_stlSlices != null) { // add geometries if (CurrentSlice >= 0 && CurrentSlice < _stlSlices.Count && _stlSlices[CurrentSlice] != null) { var stlSlice = _stlSlices[CurrentSlice]; // tiles for (int i = 0; i < stlSlice.Tiles?.Count; i++) { MShader.AddDefault(stlSlice.Tiles[i], _tileColor); } // contours for (int i = 0; i < stlSlice.ContourLines?.Count; i++) { MShader.AddDefault(stlSlice.ContourLines[i], MGLShader.Green); } // hatches for (int i = 0; i < stlSlice.HatchLines?.Count; i++) { MShader.AddDefault(stlSlice.HatchLines[i], MGLShader.White); } } // stop if new render is requested ctIn.ThrowIfCancellationRequested(); // get base transform var baseTransform = GeometricArithmeticModule.GetTranslationTransformationMatrix( StlModelReferencePoint.X, StlModelReferencePoint.Y ); // render fiducials in parent's reference frame foreach (var fiducial in Fiducials) { var transform = GeometricArithmeticModule.CombineTransformations( baseTransform, GeometricArithmeticModule.GetTranslationTransformationMatrix( fiducial.X, fiducial.Y, fiducial.Z ) ); foreach (var geometry in _fiducialPattern) { var clone = (IMarkGeometry)geometry.Clone(); clone.Transform(transform); MShader.AddDefault(clone, _fiducialColor); } } } // stop if new render is requested ctIn.ThrowIfCancellationRequested(); MShader.Render(); } ); }