Files
Shi.Ji e31d3560bb 添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
2026-05-18 11:43:09 +08:00

347 lines
15 KiB
C#

using MainShell.Common;
using MainShell.Models.Wafer;
using MainShell.Recipe.BaseBoard.Model;
using System;
using System.Collections.Generic;
using System.Linq;
namespace MainShell.Process
{
public class DieTransferPathGenerator : IDieTransferPathGenerator
{
public DieTransferPathPlan Generate(DieTransferPathRequest request)
{
return GenerateByRegion(request);
}
public DieTransferPathRegionPlan GenerateByRegion(DieTransferPathRequest request)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
DieTransferPlanningContext planningContext = DieTransferPlanningContext.Create(request);
int effectiveCount = Math.Min(planningContext.AvailablePadCount, planningContext.AvailableDieCount);
List<PadTransferRow> remainingPadRows;
List<DieTransferRow> remainingDieRows;
List<PadTransferRow> activePadRows = DieTransferPlanningContext.TrimPadRows(planningContext.PadRows, effectiveCount, out remainingPadRows);
List<DieTransferRow> activeDieRows = DieTransferPlanningContext.TrimDieRows(planningContext.DieRows, effectiveCount, out remainingDieRows);
DieTransferPathRegionPlan pathPlan = GenerateByRows(activePadRows, activeDieRows, planningContext.TransPathType);
List<Pad> remainingPads = GetOrderedPads(remainingPadRows);
List<Die> remainingDies = GetOrderedDies(remainingDieRows);
pathPlan.AvailableDieCount = planningContext.AvailableDieCount;
pathPlan.AvailablePadCount = planningContext.AvailablePadCount;
pathPlan.RemainingPads = remainingPads;
pathPlan.RemainingDies = remainingDies;
pathPlan.RemainingPadRows = DieTransferPlanningContext.CreatePadRows(remainingPads, planningContext.SubstrateRegion, planningContext.PadRowDirectionStrategy);
pathPlan.RemainingDieRows = DieTransferPlanningContext.CreateDieRows(remainingDies, planningContext.DieRegion, planningContext.SkipNgDie, planningContext.DieRowDirectionStrategy);
pathPlan.RemainingSubstrateRegion = CreateRegionFromPads(remainingPads);
pathPlan.RemainingDieRegion = CreateRegionFromDies(remainingDies);
return pathPlan;
}
public DieTransferPathRegionPlan GenerateByCandidates(
IReadOnlyCollection<Pad> padCandidates,
IReadOnlyCollection<Die> dieCandidates,
TransPathType transPathType,
bool skipNgDie,
DieTransferRowTraversalStrategy padRowDirectionStrategy,
DieTransferRowTraversalStrategy dieRowDirectionStrategy)
{
DieTransferPathRequest request = new DieTransferPathRequest();
request.PadCandidates = padCandidates ?? Array.Empty<Pad>();
request.DieCandidates = dieCandidates ?? Array.Empty<Die>();
request.TransPathType = transPathType;
request.SkipNgDie = skipNgDie;
request.PadRowDirectionStrategy = padRowDirectionStrategy;
request.DieRowDirectionStrategy = dieRowDirectionStrategy;
return GenerateByRegion(request);
}
public DieTransferPathRegionPlan GenerateByRows(
IReadOnlyCollection<PadTransferRow> padRows,
IReadOnlyCollection<DieTransferRow> dieRows,
TransPathType transPathType)
{
IReadOnlyCollection<PadTransferRow> safePadRows = padRows ?? Array.Empty<PadTransferRow>();
IReadOnlyCollection<DieTransferRow> safeDieRows = dieRows ?? Array.Empty<DieTransferRow>();
List<Pad> orderedPads = GetOrderedPads(safePadRows);
List<Die> orderedDies = GetOrderedDies(safeDieRows);
List<DieTransferPathStep> steps = CreateSteps(orderedDies, orderedPads, transPathType);
List<Pad> remainingPads = CreateRemainingPads(orderedPads, steps);
List<Die> remainingDies = CreateRemainingDies(orderedDies, steps);
DieTransferPathRegionPlan pathPlan = new DieTransferPathRegionPlan();
pathPlan.TransPathType = transPathType;
pathPlan.AvailablePadCount = GetAvailablePadCount(safePadRows);
pathPlan.AvailableDieCount = GetAvailableDieCount(safeDieRows);
pathPlan.Steps = steps;
pathPlan.RemainingPads = remainingPads;
pathPlan.RemainingDies = remainingDies;
pathPlan.RemainingPadRows = CreateRemainingPadRows(safePadRows, remainingPads);
pathPlan.RemainingDieRows = CreateRemainingDieRows(safeDieRows, remainingDies);
pathPlan.RemainingSubstrateRegion = CreateRegionFromPads(remainingPads);
pathPlan.RemainingDieRegion = CreateRegionFromDies(remainingDies);
return pathPlan;
}
private static List<DieTransferPathStep> CreateSteps(IReadOnlyList<Die> dies, IReadOnlyList<Pad> pads, TransPathType transPathType)
{
return transPathType == TransPathType.Nearest
? BuildNearestSteps(dies, pads, transPathType)
: BuildSequenceSteps(dies, pads, transPathType);
}
private static List<DieTransferPathStep> BuildSequenceSteps(IReadOnlyList<Die> dies, IReadOnlyList<Pad> pads, TransPathType transPathType)
{
int stepCount = Math.Min(dies.Count, pads.Count);
List<DieTransferPathStep> steps = new List<DieTransferPathStep>(stepCount);
for (int i = 0; i < stepCount; i++)
{
steps.Add(CreateStep(i + 1, dies[i], pads[i], transPathType));
}
return steps;
}
private static List<DieTransferPathStep> BuildNearestSteps(IReadOnlyList<Die> dies, IReadOnlyList<Pad> pads, TransPathType transPathType)
{
List<Die> remainingDies = (dies ?? Array.Empty<Die>()).Where(die => die != null).ToList();
List<DieTransferPathStep> steps = new List<DieTransferPathStep>(Math.Min(remainingDies.Count, pads.Count));
int stepIndex = 1;
foreach (Pad pad in pads)
{
if (remainingDies.Count == 0)
{
break;
}
Die nearestDie = SelectNearestDie(pad, remainingDies);
steps.Add(CreateStep(stepIndex, nearestDie, pad, transPathType));
remainingDies.Remove(nearestDie);
stepIndex++;
}
return steps;
}
private static Die SelectNearestDie(Pad pad, IReadOnlyList<Die> dies)
{
Die selectedDie = null;
double bestDistance = double.MaxValue;
for (int index = 0; index < dies.Count; index++)
{
Die die = dies[index];
double currentDistance = CalculateSquaredDistance(die.X, die.Y, pad.X, pad.Y);
if (currentDistance < bestDistance)
{
selectedDie = die;
bestDistance = currentDistance;
}
}
return selectedDie;
}
private static double CalculateSquaredDistance(double sourceX, double sourceY, double targetX, double targetY)
{
double deltaX = sourceX - targetX;
double deltaY = sourceY - targetY;
return (deltaX * deltaX) + (deltaY * deltaY);
}
private static DieTransferPathStep CreateStep(int stepIndex, Die die, Pad pad, TransPathType transPathType)
{
DieTransferPathStep step = new DieTransferPathStep();
step.StepIndex = stepIndex;
step.DieRow = die.Row;
step.DieColumn = die.Column;
step.PadRow = pad.Row;
step.PadColumn = pad.Column;
step.DieX = die.X;
step.DieY = die.Y;
step.PadX = pad.X;
step.PadY = pad.Y;
step.TransPathType = transPathType;
return step;
}
private static int GetAvailablePadCount(IEnumerable<PadTransferRow> padRows)
{
return (padRows ?? Array.Empty<PadTransferRow>())
.Where(row => row != null)
.Sum(row => row.AvailableCount);
}
private static int GetAvailableDieCount(IEnumerable<DieTransferRow> dieRows)
{
return (dieRows ?? Array.Empty<DieTransferRow>())
.Where(row => row != null)
.Sum(row => row.AvailableCount);
}
private static List<Pad> GetOrderedPads(IEnumerable<PadTransferRow> padRows)
{
List<Pad> orderedPads = new List<Pad>();
foreach (PadTransferRow padRow in (padRows ?? Array.Empty<PadTransferRow>()).Where(row => row != null).OrderBy(row => row.RowIndex))
{
orderedPads.AddRange(padRow.GetAvailablePads());
}
return orderedPads;
}
private static List<Die> GetOrderedDies(IEnumerable<DieTransferRow> dieRows)
{
List<Die> orderedDies = new List<Die>();
foreach (DieTransferRow dieRow in (dieRows ?? Array.Empty<DieTransferRow>()).Where(row => row != null).OrderBy(row => row.RowIndex))
{
orderedDies.AddRange(dieRow.GetAvailableDies());
}
return orderedDies;
}
private static List<PadTransferRow> CreateRemainingPadRows(IEnumerable<PadTransferRow> sourceRows, IReadOnlyCollection<Pad> remainingPads)
{
HashSet<string> remainingPadKeys = CreatePointKeys(remainingPads, pad => pad.Row, pad => pad.Column);
List<PadTransferRow> remainingPadRows = new List<PadTransferRow>();
foreach (PadTransferRow sourceRow in (sourceRows ?? Array.Empty<PadTransferRow>()).Where(row => row != null).OrderBy(row => row.RowIndex))
{
List<Pad> rowPads = (sourceRow.Pads ?? new List<Pad>())
.Where(pad => pad != null && remainingPadKeys.Contains(CreatePointKey(pad.Row, pad.Column)))
.OrderBy(pad => pad.Column)
.ToList();
if (rowPads.Count == 0)
{
continue;
}
PadTransferRow remainingRow = new PadTransferRow();
remainingRow.RowIndex = sourceRow.RowIndex;
remainingRow.Direction = sourceRow.Direction;
remainingRow.Pads = rowPads;
remainingPadRows.Add(remainingRow);
}
return remainingPadRows;
}
private static List<DieTransferRow> CreateRemainingDieRows(IEnumerable<DieTransferRow> sourceRows, IReadOnlyCollection<Die> remainingDies)
{
HashSet<string> remainingDieKeys = CreatePointKeys(remainingDies, die => die.Row, die => die.Column);
List<DieTransferRow> remainingDieRows = new List<DieTransferRow>();
foreach (DieTransferRow sourceRow in (sourceRows ?? Array.Empty<DieTransferRow>()).Where(row => row != null).OrderBy(row => row.RowIndex))
{
List<Die> rowDies = (sourceRow.Dies ?? new List<Die>())
.Where(die => die != null && remainingDieKeys.Contains(CreatePointKey(die.Row, die.Column)))
.OrderBy(die => die.Column)
.ToList();
if (rowDies.Count == 0)
{
continue;
}
DieTransferRow remainingRow = new DieTransferRow();
remainingRow.RowIndex = sourceRow.RowIndex;
remainingRow.Direction = sourceRow.Direction;
remainingRow.SkipNgDie = sourceRow.SkipNgDie;
remainingRow.Dies = rowDies;
remainingDieRows.Add(remainingRow);
}
return remainingDieRows;
}
private static HashSet<string> CreatePointKeys<TPoint>(IEnumerable<TPoint> points, Func<TPoint, int> getRow, Func<TPoint, int> getColumn)
where TPoint : class
{
HashSet<string> pointKeys = new HashSet<string>();
foreach (TPoint point in points ?? Array.Empty<TPoint>())
{
if (point == null)
{
continue;
}
pointKeys.Add(CreatePointKey(getRow(point), getColumn(point)));
}
return pointKeys;
}
private static List<Pad> CreateRemainingPads(IReadOnlyList<Pad> orderedPads, IReadOnlyList<DieTransferPathStep> steps)
{
HashSet<string> usedPadKeys = new HashSet<string>();
foreach (DieTransferPathStep step in steps ?? Array.Empty<DieTransferPathStep>())
{
usedPadKeys.Add(CreatePointKey(step.PadRow, step.PadColumn));
}
return (orderedPads ?? Array.Empty<Pad>())
.Where(pad => pad != null && !usedPadKeys.Contains(CreatePointKey(pad.Row, pad.Column)))
.ToList();
}
private static List<Die> CreateRemainingDies(IReadOnlyList<Die> orderedDies, IReadOnlyList<DieTransferPathStep> steps)
{
HashSet<string> usedDieKeys = new HashSet<string>();
foreach (DieTransferPathStep step in steps ?? Array.Empty<DieTransferPathStep>())
{
usedDieKeys.Add(CreatePointKey(step.DieRow, step.DieColumn));
}
return (orderedDies ?? Array.Empty<Die>())
.Where(die => die != null && !usedDieKeys.Contains(CreatePointKey(die.Row, die.Column)))
.ToList();
}
private static string CreatePointKey(int row, int column)
{
return $"{row}:{column}";
}
private static DieTransferRegion CreateRegionFromPads(IEnumerable<Pad> pads)
{
List<Pad> availablePads = (pads ?? Array.Empty<Pad>()).Where(pad => pad != null).ToList();
if (availablePads.Count == 0)
{
return null;
}
DieTransferRegion region = new DieTransferRegion();
region.StartRow = availablePads.Min(pad => pad.Row);
region.StartCol = availablePads.Min(pad => pad.Column);
region.EndRow = availablePads.Max(pad => pad.Row);
region.EndCol = availablePads.Max(pad => pad.Column);
return region;
}
private static DieTransferRegion CreateRegionFromDies(IEnumerable<Die> dies)
{
List<Die> availableDies = (dies ?? Array.Empty<Die>()).Where(die => die != null).ToList();
if (availableDies.Count == 0)
{
return null;
}
DieTransferRegion region = new DieTransferRegion();
region.StartRow = availableDies.Min(die => die.Row);
region.StartCol = availableDies.Min(die => die.Column);
region.EndRow = availableDies.Max(die => die.Row);
region.EndCol = availableDies.Max(die => die.Column);
return region;
}
}
}