private (string LayerName, MarkGeometryArc Arc) ParseArc(AdvancedLineStreamReader readerIn) { var(success, layerName) = ReadLayerName(readerIn, "AcDbCircle"); if (success) { var result1 = readerIn.FindConsecutiveLines( "100", "AcDbCircle" ); if (!result1.Success) { return(null, null); } } MarkGeometryPoint centrePoint = ReadPointFast(readerIn); // read radius 40 readerIn.ReadLine(); double radius = double.Parse(readerIn.ReadLine()); var result2 = readerIn.FindConsecutiveLines( "100", "AcDbArc" ); if (!result2.Success) { return(null, null); } // read angle 50 readerIn.ReadLine(); var startAngle = double.Parse(readerIn.ReadLine()); // read angle 60 readerIn.ReadLine(); var endAngle = double.Parse(readerIn.ReadLine()); var arc = new MarkGeometryArc( centrePoint, radius, // convert angle to radians GeometricArithmeticModule.ToRadians(startAngle), GeometricArithmeticModule.ToRadians(endAngle) ); return(layerName, arc); }
private static (string Layer, IMarkGeometry Geometry) TryParseCircle(StreamReader readerIn) { string layerName = null; IMarkGeometry geometry = null; while (true) { var(found, line) = SkipUntil(readerIn, MatchLayerOrCircle); if (!found) { break; } switch (MatchLayerOrCircle.Match(line).Value.Trim()) { case "8": layerName = readerIn.ReadLine(); break; case "AcDbCircle": MarkGeometryPoint centre = TryParsePoint(readerIn); if (centre == null) { throw new Exception("Failed to parse centre point of arc"); } if (!SkipUntil(readerIn, MatchGroupCodeForRadius).Found) { throw new Exception("Failed to parse arc radius"); } double radius = double.Parse(readerIn.ReadLine()); geometry = new MarkGeometryCircle(centre, radius) { LayerName = layerName }; return(layerName, geometry); default: throw new Exception($"Matched circle attribute is not supported: `{line}`"); } } return(layerName, geometry); }
public MSTLSlice(List <MContourStructure> contours) : this() { NumberOfContours = contours.Count; MarkGeometryPoint lastPoint = null; foreach (var contourStructure in contours) { var(lines, minLineLength, perimeter) = GeometricArithmeticModule.GetLinesAndStatistics( contourStructure.ToPoints() ); ContourLines.AddRange( lines ); if (minLineLength < MinVectorLength) { MinVectorLength = minLineLength; } _totalContourMarkDistance += perimeter; NumberOfJoints += (lines.Count - 1); if (lines.Count > 0) { if (lastPoint != null) { // measure and track the jump distance between the last contour and this _totalContourJumpDistance += GeometricArithmeticModule.ABSMeasure(lastPoint, lines[0].StartPoint); } lastPoint = lines[0].StartPoint; } } _contourQuadTree = new ContourQuadTree(ContourLines); Extents = GeometricArithmeticModule.CalculateExtents(ContourLines); }
public static List <MTileDescription> ToTiles(MTileSettings tileSettings, GeometryExtents <double> extents) { var tiles = new List <MTileDescription>(); double refWidth = extents.Width + tileSettings.XPadding; double refHeight = extents.Height + tileSettings.YPadding; int nRows = (int)Math.Ceiling(refHeight / tileSettings.YSize); int nColumns = (int)Math.Ceiling(refWidth / tileSettings.XSize); var _halfTileWidth = 0.5 * tileSettings.XSize; var _halfTileHeight = 0.5 * tileSettings.YSize; var _centre = extents.Centre - new MarkGeometryPoint(0.5 * (nColumns * tileSettings.XSize), 0.5 * (nRows * tileSettings.YSize)); int counter = 0; for (int row = 0; row < nRows; row++) { for (int col = 0; col < nColumns; col++) { var centrePoint = new MarkGeometryPoint( (col * tileSettings.XSize) + _halfTileWidth, (row * tileSettings.YSize) + _halfTileHeight ); GeometricArithmeticModule.Translate(centrePoint, _centre.X + tileSettings.XOffset, _centre.Y + tileSettings.YOffset); tiles.Add( new MTileDescription( counter++, centrePoint.X, centrePoint.Y, tileSettings.XSize, tileSettings.YSize ) ); } } return(tiles); }
protected static double[] ToDouble(MarkGeometryPoint point) { return(new double[] { point.X, point.Y }); }
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 bool GenerateHatches(MHatchSettings settings) { HatchLines.Clear(); _totalHatchesJumpDistance = 0; _totalHatchesMarkDistance = 0; var lines = new List <MarkGeometryLine>(); var angleRad = GeometricArithmeticModule.ToRadians(settings.Angle); var size = Extents.Hypotenuse; var howmany = (int)Math.Ceiling(size / settings.Pitch); var yStart = Extents.Centre.Y - (0.5 * size); // generate lines to calculate intersections for hatch if (settings.Style == HatchStyle.RASTER || settings.Style == HatchStyle.RASTER_GRID) { for (int i = 0; i < howmany; i++) { double y = yStart + (i * settings.Pitch); var line = new MarkGeometryLine( new MarkGeometryPoint( -size + Extents.Centre.X, y ), new MarkGeometryPoint( size + Extents.Centre.X, y ) ); // apply angular rotation GeometricArithmeticModule.Rotate(line, 0, 0, angleRad, Extents.Centre.X, Extents.Centre.Y, Extents.Centre.Z); lines.Add(line); } } else if (settings.Style == HatchStyle.SERPENTINE || settings.Style == HatchStyle.SERPENTINE_GRID) { for (int i = 0; i < howmany; i++) { double y = yStart + (i * settings.Pitch); if (i % 2 == 0) { var line = new MarkGeometryLine( new MarkGeometryPoint( -size + Extents.Centre.X, y ), new MarkGeometryPoint( size + Extents.Centre.X, y ) ); // apply angular rotation GeometricArithmeticModule.Rotate(line, 0, 0, angleRad, Extents.Centre.X, Extents.Centre.Y, Extents.Centre.Z); lines.Add(line); } else { var line = new MarkGeometryLine( new MarkGeometryPoint( size + Extents.Centre.X, y ), new MarkGeometryPoint( -size + Extents.Centre.X, y ) ); // apply angular rotation GeometricArithmeticModule.Rotate(line, 0, 0, angleRad, Extents.Centre.X, Extents.Centre.Y, Extents.Centre.Z); lines.Add(line); } } } // duplicate lines if using grid var perpendicularAngleForGridLines = GeometricArithmeticModule.ToRadians(90); if (settings.Style == HatchStyle.RASTER_GRID || settings.Style == HatchStyle.SERPENTINE_GRID) { int startIndex = lines.Count - 1; for (int i = startIndex; i >= 0; i--) { var ln = (MarkGeometryLine)lines[i].Clone(); GeometricArithmeticModule.Rotate(ln, 0, 0, perpendicularAngleForGridLines, Extents.Centre.X, Extents.Centre.Y, Extents.Centre.Z); lines.Add(ln); } } // used to track jumps MarkGeometryPoint lastPoint = null; // generate hatch lines with extension for (int i = 0; i < lines.Count; i++) { List <MarkGeometryPoint> intersections = _contourQuadTree.Intersect(lines[i])?.ToList(); if (intersections == null) { continue; } int startIndex = (settings.Invert) ? 1 : 0; int endIndex = intersections.Count - 1; while (startIndex < endIndex) { var hatch = new MarkGeometryLine( intersections[startIndex], intersections[startIndex + 1] ); HatchLines.Add(hatch); // increase mark and jump distance if (lastPoint != null) { _totalHatchesJumpDistance += GeometricArithmeticModule.ABSMeasure2D( lastPoint, hatch.StartPoint ); } _totalHatchesMarkDistance += hatch.Length; lastPoint = hatch.EndPoint; startIndex += 2; } } return(true); }
public async Task <Matrix4x4> GetAbsoluteTransform(MRecipeBaseNode node, Matrix4x4 parentTransform, CancellationToken ctIn) { if (parentTransform == null) { parentTransform = GeometricArithmeticModule.GetDefaultTransformationMatrix(); } // node has no fiducials, hences it's position // is relative to its parent if (node.Fiducials.Count <= 0) { return(GeometricArithmeticModule.CombineTransformations( parentTransform, node.TransformInfo.ToMatrix4x4() )); } // attempt to retrieve tasksHandler; handles process specific stage motion // camera, find n centre, etc. IProcessConfigurationTasksHandler tasksHandler = GetClosestConfigurationTasksHandler(node); if (tasksHandler == null) { throw new Exception("Failed to retrieve a Task Handler for the closest process mode"); } // buffer to store estimated and measured fiducials var estimatedPoints = new List <MarkGeometryPoint>(); var measuredPoints = new List <MarkGeometryPoint>(); for (int i = 0; i < node.Fiducials.Count; i++) { var estimatedPosition = new MarkGeometryPoint( node.Fiducials[i].X, node.Fiducials[i].Y ); // transform to parents space estimatedPosition.Transform(parentTransform); estimatedPoints.Add(estimatedPosition); // move camera to position await tasksHandler.FocusCameraAtXY( estimatedPosition.X, estimatedPosition.Y, ctIn ); // get measured position var results = await tasksHandler.TakeMeasurement(); // handle results not found if (!results.Found) { throw new Exception("Failed to find fiducial"); } // store measured point measuredPoints.Add( new MarkGeometryPoint( results.Position.X, results.Position.Y ) ); } return(GeometricArithmeticModule.CombineTransformations( parentTransform, MAlignmentCalculator.GetAlignmentTransform( node.AlignmentType, estimatedPoints, measuredPoints ) )); }
public TimeSpan EstimateProcessTime(MRecipeDeviceLayer layer) { const double kConst = 0.000001; double totalTaktTime = 0; IMarkParametersComplete processParams = FetchDXFParameters(layer); if (processParams == null) { return(TimeSpan.Zero); } int numOfJoints = 0; double jumpDistance = 0; double markDistance = 0; double minX = double.MaxValue; double minY = double.MaxValue; double maxX = double.MinValue; double maxY = double.MinValue; MarkGeometryPoint lastPosition = null; foreach (var geometry in FetchDXF(layer)) { if (geometry is MarkGeometryPoint point) { if (lastPosition != null) { jumpDistance += GeometricArithmeticModule.ABSMeasure2D(lastPosition, point); } markDistance += point.Perimeter; lastPosition = point; } else if (geometry is MarkGeometryLine line) { if (lastPosition != null) { jumpDistance += GeometricArithmeticModule.ABSMeasure2D(lastPosition, line.StartPoint); } markDistance += line.Perimeter; lastPosition = line.EndPoint; } else if (geometry is MarkGeometryCircle circle) { if (lastPosition != null) { jumpDistance += GeometricArithmeticModule.ABSMeasure2D( lastPosition, GeometricArithmeticModule.GetPointAtPosition( circle, 0 ) ); } markDistance += circle.Perimeter; numOfJoints += Math.Max(circle.VertexCount - 1, 0); lastPosition = GeometricArithmeticModule.GetPointAtPosition(circle, 1.0); } else if (geometry is MarkGeometryArc arc) { if (lastPosition != null) { jumpDistance += GeometricArithmeticModule.ABSMeasure2D(lastPosition, arc.StartPoint); } markDistance += arc.Perimeter; numOfJoints += Math.Max(arc.VertexCount - 1, 0); lastPosition = arc.EndPoint; } else if (geometry is MarkGeometryPath path) { if (lastPosition != null) { jumpDistance += GeometricArithmeticModule.ABSMeasure2D(lastPosition, path.StartPoint); } markDistance += path.Perimeter; numOfJoints += Math.Max(path.Points.Count - 1, 0); lastPosition = path.EndPoint; } if (geometry.Extents.MinX < minX) { minX = geometry.Extents.MinX; } if (geometry.Extents.MinY < minY) { minY = geometry.Extents.MinY; } if (geometry.Extents.MaxX > maxX) { maxX = geometry.Extents.MaxX; } if (geometry.Extents.MaxY > maxY) { maxY = geometry.Extents.MaxY; } } double taktTime = ( (markDistance / processParams.MarkSpeed) + (jumpDistance / processParams.JumpSpeed) + (kConst * numOfJoints * (processParams.JumpDelay_us + processParams.MarkDelay - processParams.Nprev)) ); // account for repeats and stepping between tiles - convert millisecond to second totalTaktTime += ((taktTime * processParams.Passes) + (0.001 * layer.TileDescriptions.Count() * processParams.SettlingTimems)); return(TimeSpan.FromSeconds(Math.Round(totalTaktTime, 4))); }
public IntersectionsBinaryTree(MarkGeometryPoint origin, MarkGeometryPoint point) : this(origin) { Insert(point); }
public static bool IsLesser(MarkGeometryPoint origin, MarkGeometryPoint p1, MarkGeometryPoint p2) { return(GeometricArithmeticModule.ABSMeasure2D(origin, p1) < GeometricArithmeticModule.ABSMeasure2D(origin, p2)); }