using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Threading; using System.Windows; using System.Windows.Threading; using UtilityService; using Vinno.DataManager.Data; using Vinno.DataManager.Infrastructure; using Vinno.DataManager.Infrastructure.Interfaces; using Vinno.DataManager.Utilities; using Vinno.DataTypes; using Vinno.Enums; using Vinno.Infrastructure; using Vinno.Infrastructure.Enums; using Vinno.Infrastructure.Interfaces; using Vinno.Infrastructure.Utilities; using Vinno.Models.Base; using Vinno.Models.Base.Modes; using Vinno.Models.Base.Parameters; using Vinno.Models.Base.VisualAreas; using Vinno.Models.Base.Visuals; using Vinno.Models.Dicom.Replay.Modes; using Vinno.Models.SpecificImpl.Modes; using Vinno.Modules.MeasureModule.Calculators; using Vinno.Modules.MeasureModule.ItemMetas; using Vinno.Modules.MeasureModule.Items; using Vinno.Modules.MeasureModule.Results; using Vinno.Modules.RenderModule; using Vinno.Services.InputServices; using Vinno.Services.MessageService; using Vinno.Utilities; using Vinno.vCloud.Report.JsonConverters; namespace Vinno.Modules.MeasureModule.Primitives.SRMeasure { public static class SRPointTrans { //Scream Point To ImgPoint public static DPoint TransPointS2I(DPoint srcPoint, double roundw, double roundh, double urmw, double urmh, int datew, int dateh, bool limit = true) { double Scalarx = (double) datew / urmw; double Scalary = (double) dateh / urmh; DPoint urmzeroPoint=new DPoint(-urmw/2,(roundh- urmh) /2); DPoint outPoint = new DPoint((srcPoint.X - urmzeroPoint.X) * Scalarx, (srcPoint.Y - urmzeroPoint.Y) * Scalary); if (limit) { if (outPoint.X < 0) outPoint.X = 0; if (outPoint.X > (datew - 1)) outPoint.X = datew - 1; if (outPoint.Y < 0) outPoint.Y = 0; if (outPoint.Y > (dateh - 1)) outPoint.Y = dateh - 1; } return outPoint; } //Scream Point To ImgPoint public static DPoint TransPointI2S(DPoint srcPoint, double roundw, double roundh, double urmw, double urmh, int datew, int dateh) { double Scalarx = (double)urmw/ datew; double Scalary = (double) urmh/ dateh ; DPoint urmzeroPoint = new DPoint(-urmw / 2, (roundh - urmh) / 2); DPoint outPoint = new DPoint(srcPoint.X * Scalarx+ urmzeroPoint.X, srcPoint.Y * Scalary + urmzeroPoint.Y); return outPoint; } } // 用于 public class SRStraightCurvatureLineMeasure : StraightCurvatureLine { private bool calflag = false; public SRStraightCurvatureLineMeasure(ItemMeta meta, IMeasureItem parent):base(meta, parent) { } protected override bool OnExecute(PointInfo args) { if (args.VisualArea is ISRDicom) { var dicomvisual = args.VisualArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (args.VisualArea.Mode == null || !isSRDen) { return false; } } else { var modewithurm = args.VisualArea.Mode as IModeWithURM; if (modewithurm == null||modewithurm?.URMStyle!="URM(Den)") return false; } calflag = false; var preState = State; var result = base.OnExecute(args); if (result && preState == ItemStates.Running && State == ItemStates.Finished) { calflag = true; } return result; } protected override void OnExecuted(PointInfo args) { if (GeoFeature != null && Calculator != null&& calflag) { Calculator.Calculate(); } } internal static StraightCurvatureLine CreateSRStraightCurvatureLineMeasure(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.SRStraightCurvatureLineMeasure) { throw new ArgumentException(); } var item = new SRStraightCurvatureLineMeasure(meta, parent); item.Calculator = new SRStraightCurvatureLineCal(item); return item; } internal class SRStraightCurvatureLineCal : Calculator { internal static readonly string SRkey = "SRCurvature"; protected internal override string[] SupportedOutputKeys { get { return new[] { SRkey }; } } public SRStraightCurvatureLineCal(StraightCurvatureLine straightLine) : base(straightLine) { } public SRStraightCurvatureLineCal() { } protected override void OnCalculate() { var wizardManager = ServiceManager.Instance.GetService(); wizardManager.Startup("URM", "Calculating...", CalculatSRCurvature, double.NaN, WizardButtonEnum.None); } private void CalculatSRCurvature() { TaskManagerFactory.Instance.GetTaskManager("Calculating") .StartNewTaskProxy("CalculatSRCurvature", CalculteSRCurvature, OnSRCurvatureCalculated); } private void CalculteSRCurvature(TaskProxy proxy) { StraightLineFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (!isSRDen) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if(modewithURM.URMStyle!="URM(Den)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } if (srcArray.Length != 8 * width * height) { _delayAction.BeginInvoke(); return; } double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; DPoint startDPoint = SRPointTrans.TransPointS2I(feature.StartPoint, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); DPoint endDPoint = SRPointTrans.TransPointS2I(feature.EndPoint, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); if (startDPoint.X < 0 || startDPoint.X > width || endDPoint.X < 0 || endDPoint.X > width || startDPoint.Y < 0 || startDPoint.Y > height || endDPoint.Y < 0 || endDPoint.Y > height) return; int outPointsNum = 0; double curvature = 0; var urmcal = feature.HostArea.Mode as IURMCal; if(urmcal == null) return; double[] outPoints = urmcal.GetSRCurvature(srcArray.Start, width, height, startDPoint.X, startDPoint.Y, endDPoint.X, endDPoint.Y, ref curvature, ref outPointsNum); DPoint[] points = new DPoint[outPointsNum]; for (int i = 0; i < outPointsNum; i++) { DPoint imgpoint = new DPoint(outPoints[i], outPoints[i + outPointsNum]); points[i] = SRPointTrans.TransPointI2S(imgpoint, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); } List autoLines = new List { new ManualTraceFeature(points, feature.Creator, feature.XUnit, feature.YUnit) }; ServiceManager.MainDispatcher.Invoke(UpdateChildFeatures, autoLines); feature.UpdateValue(PrimaryOutput, RoundValue(curvature, GetResultDigits(PrimaryOutput)), Unit.None); } public void UpdateChildFeatures(List autoLines) { var feature = RefItem.GeoFeature; if (feature != null) feature.UpdateChildFeatures(autoLines); } private void OnSRCurvatureCalculated(TaskProxy proxy) { IWizardManager manager = ServiceManager.Instance.GetService(); using (manager.ClosingWizard()) { var showError = false; if (proxy.Task.IsCanceled) { Logger.WriteLineInfo("Task:{0} is canceled.", proxy.Name); } else if (proxy.Task.Exception != null) { showError = true; Logger.WriteLineError("Task:{0} failed, exception: {1}.", proxy.Name, proxy.Task.Exception); } if (!showError || (bool)proxy.Tag) { manager.Close(); } else { manager.Close("SRCurvatureCalculate failed", false); } } } } } public class SRCurveCurvatureLineMeasure : Trace { private bool calflag = false; public SRCurveCurvatureLineMeasure(ItemMeta meta, IMeasureItem parent) : base(meta, parent) { } protected override bool OnExecute(PointInfo args) { var cal = Calculator as SRCurveCurvatureLineCal; if (args.VisualArea is ISRDicom) { var dicomvisual = args.VisualArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (args.VisualArea.Mode == null || !isSRDen) { return false; } } else { var modewithurm = args.VisualArea.Mode as IModeWithURM; if (modewithurm == null || modewithurm?.URMStyle != "URM(Den)") return false; } calflag = false; cal.calflag = false; var preState = State; var result = base.OnExecute(args); if (result && preState == ItemStates.Running && State == ItemStates.Finished) { calflag = true; cal.calflag = true; } return result; } protected override void OnExecuted(PointInfo args) { if (GeoFeature != null && Calculator != null && calflag) { Calculator.Calculate(); } } internal static Trace CreateSRCurveCurvatureLineMeasure(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.SRCurveCurvatureLineMeasure) { throw new ArgumentException(); } var item = new SRCurveCurvatureLineMeasure(meta, parent); item.Calculator = new SRCurveCurvatureLineCal(item); return item; } internal class SRCurveCurvatureLineCal : Calculator { public bool calflag = false; internal static readonly string URMkey = "SRCurvature"; protected internal override string[] SupportedOutputKeys { get { return new[] { URMkey }; } } public SRCurveCurvatureLineCal(Trace trace) : base(trace) { } public SRCurveCurvatureLineCal() { } protected override void OnCalculate() { if (!calflag) return; PolyLineFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (!isSRDen) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Den)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } if (srcArray.Length != 8 * width * height) { _delayAction.BeginInvoke(); return; } double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; var SrcDPoints =new List(); for (int i = 0; i < feature.Points.Count; i++) { var curpoint = SRPointTrans.TransPointS2I(feature.Points[i], regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); SrcDPoints.Add(curpoint); } if (SrcDPoints[0].X < 0 || SrcDPoints[0].X > width || SrcDPoints.Last().X < 0 || SrcDPoints.Last().X > width || SrcDPoints[0].Y < 0 || SrcDPoints[0].Y > height || SrcDPoints.Last().Y < 0 || SrcDPoints.Last().Y > height) return; double curvature = 0; var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null) return; urmcal.GetSRTraceCurvaturel(srcArray.Start, width, height, SrcDPoints, ref curvature); feature.UpdateValue(PrimaryOutput, RoundValue(curvature, GetResultDigits(PrimaryOutput)), Unit.None); } } } public class SRCurvatureMeasure : MultiMethodItem { internal SRCurvatureMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static SRCurvatureMeasure CreateSRCurvatureMeasure(ItemMeta meta, IMeasureItem parent) { if (meta.BaseType != MeasureTypes.SRCurvature) { throw new ArgumentException(); } var item = new SRCurvatureMeasure(meta, parent); return item; } } public class URMVesselMeasure : StraightLine { private bool calflag = false; public URMVesselMeasure(ItemMeta meta, IMeasureItem parent) : base(meta, parent) { } protected override bool OnExecute(PointInfo args) { if (args.VisualArea is ISRDicom) { var dicomvisual = args.VisualArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (args.VisualArea.Mode == null || !isSRDen) { return false; } } else { var modewithurm = args.VisualArea.Mode as IModeWithURM; if (modewithurm == null || modewithurm?.URMStyle != "URM(Den)") return false; } calflag = false; var preState = State; var result = base.OnExecute(args); if (result && preState == ItemStates.Running && State == ItemStates.Finished) { calflag = true; } return result; } protected override void OnExecuted(PointInfo args) { if (GeoFeature != null && Calculator != null && calflag) { Calculator.Calculate(); } } internal static URMVesselMeasure CreateURMVesselMeasure(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.URMVesselMeasure) { throw new ArgumentException(); } var item = new URMVesselMeasure(meta, parent); item.Calculator = new URMVesselMeasureCal(item); return item; } internal class URMVesselMeasureCal : Calculator { public URMVesselMeasureCal(URMVesselMeasure straightLine) : base(straightLine) { } public URMVesselMeasureCal() { } protected internal override string[] SupportedOutputKeys { get { return new[] { MeasureTerms.MaxVessDistance, MeasureTerms.MinVessDistance, MeasureTerms.MeanVessDistacne,MeasureTerms.StdVessDistance, MeasureTerms.MaxVessDiameter, MeasureTerms.MinVessDiameter, MeasureTerms.MeanVessDiameter,MeasureTerms.StdVessDiameter }; } } protected override void OnCalculate() { StraightLineFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (!isSRDen) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Den)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } if (srcArray.Length != 8 * width * height) { _delayAction.BeginInvoke(); return; } double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; DPoint startDPoint = SRPointTrans.TransPointS2I(feature.StartPoint, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); DPoint endDPoint = SRPointTrans.TransPointS2I(feature.EndPoint, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); if (startDPoint.X < 0 || startDPoint.X > width || endDPoint.X < 0 || endDPoint.X > width || startDPoint.Y < 0 || startDPoint.Y > height || endDPoint.Y < 0 || endDPoint.Y > height) return; List Points=new List(); Points.Add(startDPoint); Points.Add(endDPoint); var cmlength=Math.Sqrt(Math.Pow((feature.StartPoint.X- feature.EndPoint.X),2)+Math.Pow((feature.StartPoint.Y - feature.EndPoint.Y), 2)); var pixelscaler = UrmPhysicalwidth / width; int outPointNum = (int)(cmlength*1000); SRMeasurePoint[] outPoints=new SRMeasurePoint[outPointNum]; var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null) return; var result = urmcal.GetUrmVessMeasureResult(srcArray.Start, width, height, Points, pixelscaler, outPoints); foreach (var outputItem in Outputs) { outputItem.UpdateDescription(outputItem.Name); if (string.Equals(outputItem.Name, MeasureTerms.MaxVessDistance)) { feature.UpdateValue(outputItem, RoundValue(result.MaxVessDistance, outputItem), Unit.mm); } else if (string.Equals(outputItem.Name, MeasureTerms.MinVessDistance)) { feature.UpdateValue(outputItem, RoundValue(result.MinVessDistance, outputItem), Unit.mm); } else if (string.Equals(outputItem.Name, MeasureTerms.MeanVessDistacne)) { feature.UpdateValue(outputItem, RoundValue(result.MeanVessDistacne, outputItem), Unit.mm); } else if (string.Equals(outputItem.Name, MeasureTerms.StdVessDistance)) { feature.UpdateValue(outputItem, RoundValue(Math.Sqrt(result.VarianceVessDistance), outputItem), Unit.mm); } else if (string.Equals(outputItem.Name, MeasureTerms.MaxVessDiameter)) { feature.UpdateValue(outputItem, RoundValue(result.MaxVessDiameter, outputItem), Unit.mm); } else if (string.Equals(outputItem.Name, MeasureTerms.MinVessDiameter)) { feature.UpdateValue(outputItem, RoundValue(result.MinVessDiameter, outputItem), Unit.mm); } else if (string.Equals(outputItem.Name, MeasureTerms.MeanVessDiameter)) { feature.UpdateValue(outputItem, RoundValue(result.MeanVessDiameter, outputItem), Unit.mm); } else if (string.Equals(outputItem.Name, MeasureTerms.StdVessDiameter)) { feature.UpdateValue(outputItem, RoundValue(Math.Sqrt(result.VarianceVessDiameter), outputItem), Unit.mm); } } var maxPointIndex = result.MaxPos; var minPointIndex = result.MinPos; var srChart = ServiceManager.Instance.GetService().SrChart; srChart.Update(feature, outPoints.Select(x => new DPoint(x.X, x.Y)).ToArray(), maxPointIndex, minPointIndex); } } } internal class SRROIMeasure : Rect { private bool calflag=false; public SRROIMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static SRROIMeasure CreateSRROIMeasure(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.SRRoiDensity ) { throw new ArgumentException(); } var SRROI = new SRROIMeasure(meta, parent); SRROI.Calculator = new SRROICal(SRROI); return SRROI; } public override void DownloadValueFromPreviousItem() { } protected override bool OnExecute(PointInfo args) { var cal = Calculator as SRROICal; if (args.VisualArea is ISRDicom) { var dicomvisual = args.VisualArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (args.VisualArea.Mode == null || !isSRDen) { return false; } } else { var modewithurm = args.VisualArea.Mode as IModeWithURM; if (modewithurm == null || modewithurm?.URMStyle != "URM(Den)") return false; } calflag = false; cal.calflag = false; var preState = State; var result = base.OnExecute(args); if (result && preState == ItemStates.Running && State == ItemStates.Finished) { calflag = true; cal.calflag = true; } return result; } protected override void OnExecuted(PointInfo args) { if (GeoFeature != null && Calculator != null && calflag) { Calculator.Calculate(); } } internal sealed class SRROICal : Calculator { public bool calflag=false; public SRROICal(SRROIMeasure item) : base(item) { } public SRROICal() { } protected internal override string[] SupportedOutputKeys { get { return new[] { MeasureTerms.URMDenROI }; } } protected override void OnCalculate() { if(!calflag) return; RectFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (!isSRDen) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Den)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } if (srcArray.Length != 8 * width * height) { _delayAction.BeginInvoke(); return; } //todo 坐标转换 double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; DPoint startDPoint = SRPointTrans.TransPointS2I(feature.TopLeft, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); DPoint endDPoint = SRPointTrans.TransPointS2I(feature.BottomRight, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); if (startDPoint.X < 0 || startDPoint.X > width || endDPoint.X < 0 || endDPoint.X > width || startDPoint.Y < 0 || startDPoint.Y > height || endDPoint.Y < 0 || endDPoint.Y > height) return; int outPointsNum = 0; var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null) return; double roivel = urmcal.GetSRRoiVel(srcArray.Start, width, height, startDPoint.X, startDPoint.Y, endDPoint.X, endDPoint.Y); Outputs[0].UpdateDescription(Outputs[0].Name); feature.UpdateValue(Outputs[0], RoundValue(roivel * 100, GetResultDigits(PrimaryOutput)), Unit.percent); } } } internal class URMRectDenMeasure : Rect { private bool calflag = false; public URMRectDenMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static URMRectDenMeasure CreateURMRectDenMeasure(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.URMRectDenMeasure) { throw new ArgumentException(); } var item = new URMRectDenMeasure(meta, parent); item.Calculator = new URMRectDenMeasureCal(item); return item; } public override void DownloadValueFromPreviousItem() { } protected override bool OnExecute(PointInfo args) { var cal = Calculator as URMRectDenMeasureCal; if (args.VisualArea is ISRDicom) { var dicomvisual = args.VisualArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (args.VisualArea.Mode == null || !isSRDen) { return false; } } else { var modewithurm = args.VisualArea.Mode as IModeWithURM; if (modewithurm == null || modewithurm?.URMStyle != "URM(Den)") return false; } calflag = false; cal.calflag = false; var preState = State; var result = base.OnExecute(args); if (result && preState == ItemStates.Running && State == ItemStates.Finished) { calflag = true; cal.calflag = true; } return result; } protected override void OnExecuted(PointInfo args) { if (GeoFeature != null && Calculator != null && calflag) { Calculator.Calculate(); } } internal sealed class URMRectDenMeasureCal : Calculator { public bool calflag = false; public URMRectDenMeasureCal(URMRectDenMeasure item) : base(item) { } public URMRectDenMeasureCal() { } protected internal override string[] SupportedOutputKeys { get { return new[] { MeasureTerms.URMDenROI, MeasureTerms.URMDenFractalDim, MeasureTerms.URMDenMax, MeasureTerms.URMDenMin, MeasureTerms.URMDenMean, MeasureTerms.URMDenStd, MeasureTerms.Area, MeasureTerms.URMDenROIIn, MeasureTerms.URMDenFractalDimIn, MeasureTerms.URMDenMaxIn, MeasureTerms.URMDenMinIn, MeasureTerms.URMDenMeanIn, MeasureTerms.URMDenStdIn, MeasureTerms.URMAreaIn, MeasureTerms.URMDenROIOut, MeasureTerms.URMDenFractalDimOut, MeasureTerms.URMDenMaxOut, MeasureTerms.URMDenMinOut, MeasureTerms.URMDenMeanOut, MeasureTerms.URMDenStdOut, MeasureTerms.URMAreaOut, }; } } protected override void OnCalculate() { if (!calflag) return; RectFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (!isSRDen) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Den)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } if (srcArray.Length != 8 * width * height) { _delayAction.BeginInvoke(); return; } //todo 坐标转换 double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; DPoint startDPoint = SRPointTrans.TransPointS2I(feature.TopLeft, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); DPoint endDPoint = SRPointTrans.TransPointS2I(feature.BottomRight, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); if (startDPoint.X < 0 || startDPoint.X > width || endDPoint.X < 0 || endDPoint.X > width || startDPoint.Y < 0 || startDPoint.Y > height || endDPoint.Y < 0 || endDPoint.Y > height) return; List ImagePoint = new List(); double areaScaler = (UrmPhysicalwidth / width) * (UrmPhysicalheight / height); ImagePoint.Add(startDPoint); ImagePoint.Add(endDPoint); var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null) return; var result = urmcal.GetURMDenMeasureResult(srcArray.Start, width, height, ImagePoint,areaScaler); foreach (var outputItem in Outputs) { outputItem.UpdateDescription(outputItem.Name); if (string.Equals(outputItem.Name,MeasureTerms.URMDenROI)) { feature.UpdateValue(outputItem, RoundValue(result.RoiDen*100, outputItem), Unit.percent); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenFractalDim)) { feature.UpdateValue(outputItem, RoundValue(result.RoiFractalDim, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMax)) { feature.UpdateValue(outputItem, RoundValue(result.MaxDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMin)) { feature.UpdateValue(outputItem, RoundValue(result.MinDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMean)) { feature.UpdateValue(outputItem, RoundValue(result.MeanDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenStd)) { feature.UpdateValue(outputItem, RoundValue(Math.Sqrt(result.VarianceDensity), outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.Area)) { feature.UpdateValue(outputItem, RoundValue(result.RoiArea, outputItem), Unit.cm2); } } } } } internal class URMRectVelMeasure : Rect { private bool calflag = false; public URMRectVelMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static URMRectVelMeasure CreateURMRectVelMeasure(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.URMRectVelMeasure) { throw new ArgumentException(); } var item = new URMRectVelMeasure(meta, parent); item.Calculator = new URMRectVelMeasureCal(item); return item; } public override void DownloadValueFromPreviousItem() { } protected override bool OnExecute(PointInfo args) { var cal = Calculator as URMRectVelMeasureCal; if (args.VisualArea is ISRDicom) { var dicomvisual = args.VisualArea as ISRDicom; bool isSrVel = dicomvisual.isSRVel(); if (args.VisualArea.Mode == null || !isSrVel) { return false; } } else { var modewithurm = args.VisualArea.Mode as IModeWithURM; if (modewithurm == null || modewithurm?.URMStyle != "URM(Vel)") return false; } calflag = false; cal.calflag = false; var preState = State; var result = base.OnExecute(args); if (result && preState == ItemStates.Running && State == ItemStates.Finished) { calflag = true; cal.calflag = true; } return result; } protected override void OnExecuted(PointInfo args) { if (GeoFeature != null && Calculator != null && calflag) { Calculator.Calculate(); } } internal sealed class URMRectVelMeasureCal : Calculator { public bool calflag = false; public URMRectVelMeasureCal(URMRectVelMeasure item) : base(item) { } public URMRectVelMeasureCal() { } protected internal override string[] SupportedOutputKeys { get { return new[] { MeasureTerms.URMVelMax, MeasureTerms.URMVelMin, MeasureTerms.URMVelMean, MeasureTerms.URMVelStd, MeasureTerms.Area, MeasureTerms.URMVelMaxIn, MeasureTerms.URMVelMinIn, MeasureTerms.URMVelMeanIn, MeasureTerms.URMVelStdIn, MeasureTerms.URMAreaIn, MeasureTerms.URMVelMaxOut, MeasureTerms.URMVelMinOut, MeasureTerms.URMVelMeanOut, MeasureTerms.URMVelStdOut, MeasureTerms.URMAreaOut, }; } } protected override void OnCalculate() { if (!calflag) return; RectFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; double UrmMinVel = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRVel = dicomvisual.isSRVel(); if (!isSRVel) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); UrmMinVel = dicomvisual.GetSRMinVel(); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Vel)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; UrmMinVel = modewithURM.URMMinVel; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } //todo 坐标转换 double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; DPoint startDPoint = SRPointTrans.TransPointS2I(feature.TopLeft, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); DPoint endDPoint = SRPointTrans.TransPointS2I(feature.BottomRight, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); if (startDPoint.X < 0 || startDPoint.X > width || endDPoint.X < 0 || endDPoint.X > width || startDPoint.Y < 0 || startDPoint.Y > height || endDPoint.Y < 0 || endDPoint.Y > height) return; List ImagePoint = new List(); double areaScaler = (UrmPhysicalwidth / width) * (UrmPhysicalheight / height); ImagePoint.Add(startDPoint); ImagePoint.Add(endDPoint); var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null) return; var result = urmcal.GetURMVelMeasureResult(srcArray.Start, width, height, ImagePoint, areaScaler); foreach (var outputItem in Outputs) { outputItem.UpdateDescription(outputItem.Name); if (string.Equals(outputItem.Name, MeasureTerms.URMVelMax)) { feature.UpdateValue(outputItem, RoundValue(result.MaxVel+UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelMin)) { feature.UpdateValue(outputItem, RoundValue(result.MinVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelMean)) { feature.UpdateValue(outputItem, RoundValue(result.MeanVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelStd)) { feature.UpdateValue(outputItem, RoundValue(Math.Sqrt(result.VarianceVel), outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.Area)) { feature.UpdateValue(outputItem, RoundValue(result.RoiArea, outputItem), Unit.cm2); } } } } } internal class URMTraceDenMeasure : Trace { private bool calflag = false; public URMTraceDenMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static URMTraceDenMeasure CreateURMTraceDenMeasure(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.URMTraceDenMeasure) { throw new ArgumentException(); } meta.AddArgs(new MeasureParam(IsAutoSnapKey, "true", DefinitionPriorityEnum.Root)); var item = new URMTraceDenMeasure(meta, parent); item.Calculator = new URMTraceDenMeasureCal(item); return item; } public override void DownloadValueFromPreviousItem() { } protected override bool OnExecute(PointInfo args) { var cal = Calculator as URMTraceDenMeasureCal; if (args.VisualArea is ISRDicom) { var dicomvisual = args.VisualArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (args.VisualArea.Mode == null || !isSRDen) { return false; } } else { var modewithurm = args.VisualArea.Mode as IModeWithURM; if (modewithurm == null || modewithurm?.URMStyle != "URM(Den)") return false; } calflag = false; cal.calflag = false; var preState = State; var result = base.OnExecute(args); if (result && preState == ItemStates.Running && State == ItemStates.Finished) { calflag = true; cal.calflag = true; } return result; } protected override void OnExecuted(PointInfo args) { if (GeoFeature != null && Calculator != null && calflag) { Calculator.Calculate(); } } internal sealed class URMTraceDenMeasureCal : Calculator { public bool calflag = false; public URMTraceDenMeasureCal(URMTraceDenMeasure item) : base(item) { } public URMTraceDenMeasureCal() { } protected internal override string[] SupportedOutputKeys { get { return new[] { MeasureTerms.URMDenROI, MeasureTerms.URMDenFractalDim, MeasureTerms.URMDenMax, MeasureTerms.URMDenMin, MeasureTerms.URMDenMean, MeasureTerms.URMDenStd, MeasureTerms.Area }; } } protected override void OnCalculate() { if (!calflag) return; PolyLineFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (!isSRDen) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Den)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } if (srcArray.Length != 8 * width * height) { _delayAction.BeginInvoke(); return; } //todo 坐标转换 double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; var points = RefItem.GeoFeature.Points; List ImagePoint = new List(); for (int i = 0; i < points.Count; i++) { var point = SRPointTrans.TransPointS2I(points[i], regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); if (point.X < 0 || point.X > width || point.X < 0 || point.X > width) continue; ImagePoint.Add(point); } double areaScaler = (UrmPhysicalwidth / width) * (UrmPhysicalheight / height); var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null) return; var result = urmcal.GetURMDenMeasureResult(srcArray.Start, width, height, ImagePoint, areaScaler); foreach (var outputItem in Outputs) { outputItem.UpdateDescription(outputItem.Name); if (string.Equals(outputItem.Name, MeasureTerms.URMDenROI)) { feature.UpdateValue(outputItem, RoundValue(result.RoiDen*100, outputItem), Unit.percent); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenFractalDim)) { feature.UpdateValue(outputItem, RoundValue(result.RoiFractalDim, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMax)) { feature.UpdateValue(outputItem, RoundValue(result.MaxDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMin)) { feature.UpdateValue(outputItem, RoundValue(result.MinDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMean)) { feature.UpdateValue(outputItem, RoundValue(result.MeanDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenStd)) { feature.UpdateValue(outputItem, RoundValue(Math.Sqrt(result.VarianceDensity), outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.Area)) { feature.UpdateValue(outputItem, RoundValue(result.RoiArea, outputItem), Unit.cm2); } } } } } internal class URMTraceVelMeasure : Trace { private bool calflag = false; public URMTraceVelMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static URMTraceVelMeasure CreateURMTraceVelMeasure(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.URMTraceVelMeasure) { throw new ArgumentException(); } meta.AddArgs(new MeasureParam(IsAutoSnapKey, "true", DefinitionPriorityEnum.Root)); var item = new URMTraceVelMeasure(meta, parent); item.Calculator = new URMTraceVelMeasureCal(item); return item; } public override void DownloadValueFromPreviousItem() { } protected override bool OnExecute(PointInfo args) { var cal = Calculator as URMTraceVelMeasureCal; if (args.VisualArea is ISRDicom) { var dicomvisual = args.VisualArea as ISRDicom; bool isSrVel = dicomvisual.isSRVel(); if (args.VisualArea.Mode == null || !isSrVel) { return false; } } else { var modewithurm = args.VisualArea.Mode as IModeWithURM; if (modewithurm == null || modewithurm?.URMStyle != "URM(Vel)") return false; } calflag = false; cal.calflag = false; var preState = State; var result = base.OnExecute(args); if (result && preState == ItemStates.Running && State == ItemStates.Finished) { calflag = true; cal.calflag = true; } return result; } protected override void OnExecuted(PointInfo args) { if (GeoFeature != null && Calculator != null && calflag) { Calculator.Calculate(); } } internal sealed class URMTraceVelMeasureCal : Calculator { public bool calflag = false; public URMTraceVelMeasureCal(URMTraceVelMeasure item) : base(item) { } public URMTraceVelMeasureCal() { } protected internal override string[] SupportedOutputKeys { get { return new[] { MeasureTerms.URMVelMax, MeasureTerms.URMVelMin, MeasureTerms.URMVelMean, MeasureTerms.URMVelStd, MeasureTerms.Area }; } } protected override void OnCalculate() { if (!calflag) return; PolyLineFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; double UrmMinVel = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRVel = dicomvisual.isSRVel(); if (!isSRVel) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); UrmMinVel = dicomvisual.GetSRMinVel(); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Vel)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; UrmMinVel = modewithURM.URMMinVel; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } //todo 坐标转换 double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; var points = RefItem.GeoFeature.Points; List ImagePoint = new List(); for (int i = 0; i < points.Count; i++) { var point = SRPointTrans.TransPointS2I(points[i], regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); if (point.X < 0 || point.X > width || point.X < 0 || point.X > width) continue; ImagePoint.Add(point); } double areaScaler = (UrmPhysicalwidth / width) * (UrmPhysicalheight / height); var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null) return; var result = urmcal.GetURMVelMeasureResult(srcArray.Start, width, height, ImagePoint, areaScaler); foreach (var outputItem in Outputs) { outputItem.UpdateDescription(outputItem.Name); if (string.Equals(outputItem.Name, MeasureTerms.URMVelMax)) { feature.UpdateValue(outputItem, RoundValue(result.MaxVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelMin)) { feature.UpdateValue(outputItem, RoundValue(result.MinVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelMean)) { feature.UpdateValue(outputItem, RoundValue(result.MeanVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelStd)) { feature.UpdateValue(outputItem, RoundValue(Math.Sqrt(result.VarianceVel), outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.Area)) { feature.UpdateValue(outputItem, RoundValue(result.RoiArea, outputItem), Unit.cm2); } } } } } public class URMShellMeasure : Trace { private bool _isSmartMove; public FloatParameter ShellWidth { get; set; } internal static readonly string ShellWidthKey = "ShellWidth"; internal static readonly string ShellWidthMetaKey = "ShellWidth_Meta"; public static string ShellWidthMeta = "[1 2 3 4 5]"; public static string ShellWidthDefaultValue = "1"; public URMShellMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { if (!meta.TryGetArgValue(ShellWidthMetaKey, out var shellWidthMeta) || string.IsNullOrEmpty(shellWidthMeta)) { shellWidthMeta = ShellWidthMeta; } if (!meta.TryGetArgValue(ShellWidthKey, out var shellWidthDefaultValue) || string.IsNullOrEmpty(shellWidthDefaultValue)) { shellWidthDefaultValue = ShellWidthDefaultValue; } ShellWidth = CreateArrayFloatParam(ShellWidthKey, shellWidthMeta, shellWidthDefaultValue); ShellWidth.ValueChanged += OnShellWidthParamsChanged; } protected override bool OnExecuteMouse(PointInfo args) { if (args != null && (State == ItemStates.Waiting || State == ItemStates.Running || State == ItemStates.Finished)) { bool completed = false; if (State == ItemStates.Finished) { switch (args.Action) { case PointAction.MouseMove: case PointAction.MouseUp: return false; case PointAction.MouseDown: HandleMouseDownWhileFinished(); break; } } if (State == ItemStates.Waiting) { switch (args.Action) { case PointAction.MouseMove: case PointAction.MouseUp: return false; case PointAction.MouseDown: HandleMouseDownWhileWaiting((MultiRegionPointInfo)args, (vertices, refItem, xUnit, yUnit) => new ShellTraceFeature(vertices, refItem, xUnit, yUnit)); FirstPoint = args; if (!args.PixelPerX.AlmostEquals(0)) { float pixelThreshold = PixelThreshold.AlmostEquals(0) ? 4 : PixelThreshold; Threshold = (float)(pixelThreshold / args.PixelPerX); } break; } } else if (State == ItemStates.Running) { var points = (MultiRegionPointInfo)args; if (!GeoFeature.AnyExist(points.AllAreas)) { return false; } switch (args.Action) { case PointAction.MouseDown: IsClosed = true; GeoFeature.IsClosed = true; completed = true; break; case PointAction.MouseMove: //Use the IsAutoSnap to check if the trace need to use smart move. var measureService = ServiceManager.Instance.GetService(); double autoSnapThreshold = measureService.Settings.AutoSnapThreshold; if (IsAutoSnap && autoSnapThreshold > 0) { //Change autosnapdistance unit from cm to pixel if (FirstPoint != null) { var current = points.AllRegionPoints.FirstOrDefault(x => x.VisualArea == FirstPoint.VisualArea); if (current != null) { var length = (FirstPoint.PhyPoint - current.PhyPoint).Length; if (GeoFeature.Points.Count < 3) { _isSmartMove = false; } if (length > autoSnapThreshold * 2.0 && !_isSmartMove) { _isSmartMove = true; } // User clear points if GeoFeature.ActivePoint== current.LogicPoint, so the trace shouldn't be smart closed. if (length < autoSnapThreshold && _isSmartMove && !GeoFeature.ActivePoint.AlmostEquals(current.LogicPoint)) { IsClosed = true; GeoFeature.IsClosed = true; _isSmartMove = false; completed = true; GeoFeature.SyncStates(x => { x.AddPoint(x.Points[0]); }); GeoFeature.Points[0].SynchToMainMonitorScreen(GeoFeature.HostArea); break; } } } } foreach (var point in points.AllRegionPoints) { var geoFeature = GeoFeature.GetSpecificFeature(point.VisualArea); if (geoFeature != null) { geoFeature.AddPoint(point.LogicPoint); geoFeature.ActivePoint = point.LogicPoint; } } break; } } if (GeoFeature != null) { Calculator.Calculate(); } //Update state if (args.Action == PointAction.MouseDown) { if (State == ItemStates.Waiting || State == ItemStates.Finished) { State = ItemStates.Running; } if (State == ItemStates.Running && completed) { FinishEditing((MultiRegionPointInfo)args); } } if ((args.Action == PointAction.MouseMove || args.Action == PointAction.TouchMove) && IsClosed) { if (State == ItemStates.Running && completed) { FinishEditing((MultiRegionPointInfo)args); } } return true; } return false; } protected override bool OnExecuteTouch(PointInfo args) { if (State == ItemStates.Finished) { switch (args.Action) { case PointAction.TouchUp: case PointAction.TouchMove: return false; case PointAction.TouchDown: HandleMouseDownWhileFinished(); break; } } if (State == ItemStates.Waiting) { switch (args.Action) { case PointAction.TouchUp: case PointAction.TouchMove: return false; case PointAction.TouchDown: CaliperExtension.HideCaliper(); HandleMouseDownWhileWaiting((MultiRegionPointInfo)args, (vertices, refItem, xUnit, yUnit) => new ShellTraceFeature(vertices, refItem, xUnit, yUnit)); if (!args.PixelPerX.AlmostEquals(0)) { float pixelThreshold = PixelThreshold.AlmostEquals(0) ? 4 : PixelThreshold; Threshold = (float)(pixelThreshold / args.PixelPerX); } IsNewMeasure = true; IsCompleted = false; StartSyncIgnore(); State = ItemStates.Running; break; } } else if (State == ItemStates.Running) { var points = (MultiRegionPointInfo)args; switch (args.Action) { case PointAction.TouchUp: IsRelocatePoints = false; if (!IsIgnore) { if (!GeoFeature.ReEditing && !IsCompleted) { if (!GeoFeature.Points[0].AlmostEquals(GeoFeature.Points[GeoFeature.Points.Count / 2])) { IsCompleted = true; } } } IsNewMeasure = false; FinishEditingForTouch(points); GeoFeature.ReEditing = false; break; case PointAction.TouchMove: if (!IsIgnore) { if (IsNewMeasure && IsRelocatePoints) { RelocatePoints(points); } else { CaliperExtension.HideCaliper(); if (!GeoFeature.ReEditing) { var measureService = ServiceManager.Instance.GetService(); double autoSnapThreshold = measureService.Settings.AutoSnapThreshold; if ((IsAutoSnap) && autoSnapThreshold > 0) { var current = points.AllRegionPoints.FirstOrDefault(x => x.VisualArea == GeoFeature.HostArea); if (current != null) { var length = (GeoFeature.Points[0].PointToMainMonitorScreen(GeoFeature.HostArea) - (current.LogicPoint + ActiveTouchPointVector).PointToMainMonitorScreen(GeoFeature.HostArea)).Length; if (GeoFeature.Points.Count < 3) { IsSmartMove = false; } if (length > autoSnapThreshold * 2.0 && !IsSmartMove) { IsSmartMove = true; } if (length < autoSnapThreshold && IsSmartMove) { IsCompleted = true; IsSmartMove = false; GeoFeature.SyncStates(x => { x.AddPoint(x.Points[0]); }); FinishEditingForTouch(points); return true; } } } } foreach (var point in points.AllRegionPoints) { var geoFeature = GeoFeature.GetSpecificFeature(point.VisualArea); if (geoFeature != null) { var tempEndPoint = point.LogicPoint + ActiveTouchPointVector; if (!ServiceManager.Instance.GetService().GetParameterValue("EnableCrossRegionOperation", false) && !point.ContainerBound.Contains(tempEndPoint)) { return true; } geoFeature.AddPoint(tempEndPoint); geoFeature.ActivePoint = tempEndPoint; } } } } break; case PointAction.TouchEnter: case PointAction.TouchDown: case PointAction.HoldGesture: base.OnExecuteTouch(args); break; } } return true; } internal override MeasuredFeature CreateMeasureFeatureFrom(MeasuredFeature source) { if (source is ShellTraceFeature feature) { return new ShellTraceFeature(feature.Points, this, feature.XUnit, feature.YUnit) { HostArea = feature.HostArea, ReferenceArea = feature.ReferenceArea, FrameIndex = feature.FrameIndex, VisualAreaType = feature.VisualAreaType, IsClosed = feature.IsClosed, ActivePointIndex = -1, }; } return null; } private void OnShellWidthParamsChanged(object sender, EventArgs e) { Calculator.Calculate(); } } public class URMShellDenMeasure : URMShellMeasure { public URMShellDenMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static URMShellDenMeasure CreateURMShellDenMeasure(ItemMeta meta, IMeasureItem parent) { if (meta.BaseType != MeasureTypes.URMShellDenMeasure) { throw new ArgumentException(); } meta.AddArgs(new MeasureParam(IsAutoSnapKey, "true", DefinitionPriorityEnum.Root)); var item = new URMShellDenMeasure(meta, parent); item.Calculator = new URMShellDenMeasureCal(item); return item; } internal sealed class URMShellDenMeasureCal : Calculator { public URMShellDenMeasureCal(URMShellDenMeasure item) : base(item) { } public URMShellDenMeasureCal() { } protected internal override string[] SupportedOutputKeys { get { return new[] { MeasureTerms.URMDenROI, MeasureTerms.URMDenFractalDim, MeasureTerms.URMDenMax, MeasureTerms.URMDenMin, MeasureTerms.URMDenMean, MeasureTerms.URMDenStd, MeasureTerms.Area, MeasureTerms.URMDenROIIn, MeasureTerms.URMDenFractalDimIn, MeasureTerms.URMDenMaxIn, MeasureTerms.URMDenMinIn, MeasureTerms.URMDenMeanIn, MeasureTerms.URMDenStdIn, MeasureTerms.URMAreaIn, MeasureTerms.URMDenROIOut, MeasureTerms.URMDenFractalDimOut, MeasureTerms.URMDenMaxOut, MeasureTerms.URMDenMinOut, MeasureTerms.URMDenMeanOut, MeasureTerms.URMDenStdOut, MeasureTerms.URMAreaOut, }; } } protected override void OnCalculate() { if (RefItem.State != ItemStates.Finished) return; PolyLineFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (!isSRDen) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Den)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } if (srcArray.Length != 8 * width * height) { _delayAction.BeginInvoke(); return; } //todo 坐标转换 double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; var points = RefItem.GeoFeature.Points; List ImagePoint = new List(); for (int i = 0; i < points.Count; i++) { var point = SRPointTrans.TransPointS2I(points[i], regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height,false); if (point.X < 0 || point.X > width || point.X < 0 || point.X > width) continue; ImagePoint.Add(point); } if(ImagePoint.Count<3) return; double pixelscaler = UrmPhysicalwidth / width; var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null) return; //double ShellWidth = 10;//Todo 这一块需要修改为根据设置的shellwidth来 var result = urmcal.GetURMShellDenMeasureResult(srcArray.Start, width, height, ImagePoint, RefItem.ShellWidth.Value/10, pixelscaler, out var outshellPoints); //Todo OutShellPoint调用TransPointI2S转换为逻辑坐标用于绘制 var transpoints = new List(); foreach (var point in outshellPoints) { var transpoint = SRPointTrans.TransPointI2S(point, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); transpoints.Add(transpoint); } UpdateGeometry(transpoints); foreach (var outputItem in Outputs) { outputItem.UpdateDescription(outputItem.Name); if (string.Equals(outputItem.Name, MeasureTerms.URMDenROI)) { feature.UpdateValue(outputItem, RoundValue(result.RoiDen * 100, outputItem), Unit.percent); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenFractalDim)) { feature.UpdateValue(outputItem, RoundValue(result.RoiFractalDim, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMax)) { feature.UpdateValue(outputItem, RoundValue(result.MaxDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMin)) { feature.UpdateValue(outputItem, RoundValue(result.MinDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMean)) { feature.UpdateValue(outputItem, RoundValue(result.MeanDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenStd)) { feature.UpdateValue(outputItem, RoundValue(Math.Sqrt(result.VarianceDensity), outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.Area)) { feature.UpdateValue(outputItem, RoundValue(result.RoiArea, outputItem), Unit.cm2); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenROIIn)) { feature.UpdateValue(outputItem, RoundValue(result.InRoiDen * 100, outputItem), Unit.percent); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenFractalDimIn)) { feature.UpdateValue(outputItem, RoundValue(result.InRoiFractalDim, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMaxIn)) { feature.UpdateValue(outputItem, RoundValue(result.InMaxDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMinIn)) { feature.UpdateValue(outputItem, RoundValue(result.InMinDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMeanIn)) { feature.UpdateValue(outputItem, RoundValue(result.InMeanDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenStdIn)) { feature.UpdateValue(outputItem, RoundValue(Math.Sqrt(result.InVarianceDensity), outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMAreaIn)) { feature.UpdateValue(outputItem, RoundValue(result.InRoiArea, outputItem), Unit.cm2); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenROIOut)) { feature.UpdateValue(outputItem, RoundValue(result.OutRoiDen * 100, outputItem), Unit.percent); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenFractalDimOut)) { feature.UpdateValue(outputItem, RoundValue(result.OutRoiFractalDim, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMaxOut)) { feature.UpdateValue(outputItem, RoundValue(result.OutMaxDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMinOut)) { feature.UpdateValue(outputItem, RoundValue(result.OutMinDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenMeanOut)) { feature.UpdateValue(outputItem, RoundValue(result.OutMeanDensity, outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMDenStdOut)) { feature.UpdateValue(outputItem, RoundValue(Math.Sqrt(result.OutVarianceDensity), outputItem), Unit.None); } else if (string.Equals(outputItem.Name, MeasureTerms.URMAreaOut)) { feature.UpdateValue(outputItem, RoundValue(result.OutRoiArea, outputItem), Unit.cm2); } } } protected void UpdateGeometry(List outResult) { var geometry = new TraceLineFeature(outResult, RefItem, RefItem.GeoFeature.XUnit, RefItem.GeoFeature.YUnit, false) { IsClosed = true, }; if (RefItem.GeoFeature is ShellTraceFeature feature) { feature.UpdateChildFeatures(new List { geometry }); } } } } public class URMShellFractalDim: URMShellMeasure { public URMShellFractalDim(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static URMShellFractalDim CreateURMShellFractalDim(ItemMeta meta, IMeasureItem parent) { if (meta.BaseType != MeasureTypes.URMShellFractalDim) { throw new ArgumentException(); } meta.AddArgs(new MeasureParam(IsAutoSnapKey, "true", DefinitionPriorityEnum.Root)); var item = new URMShellFractalDim(meta, parent); item.Calculator = new URMShellFractalDimCal(item); return item; } internal sealed class URMShellFractalDimCal : Calculator { public URMShellFractalDimCal(URMShellFractalDim item) : base(item) { } public URMShellFractalDimCal() { } protected internal override string[] SupportedOutputKeys { get { return new[] { MeasureTerms.URMDenFractalDim, }; } } protected override void OnCalculate() { if (RefItem.State != ItemStates.Finished) return; PolyLineFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (!isSRDen) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Den)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } if (srcArray.Length != 8 * width * height) { _delayAction.BeginInvoke(); return; } //todo 坐标转换 double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; var points = RefItem.GeoFeature.Points; List ImagePoint = new List(); for (int i = 0; i < points.Count; i++) { var point = SRPointTrans.TransPointS2I(points[i], regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height,false); if (point.X < 0 || point.X > width || point.X < 0 || point.X > width) continue; ImagePoint.Add(point); } if (ImagePoint.Count < 3) return; double pixelscaler = UrmPhysicalwidth / width; var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null) return; var result = urmcal.GetURMShellDenMeasureResult(srcArray.Start, width, height, ImagePoint, RefItem.ShellWidth.Value / 10, pixelscaler, out var outshellPoints); //Todo OutShellPoint调用TransPointI2S转换为逻辑坐标用于绘制 var transpoints = new List(); foreach (var point in outshellPoints) { var transpoint = SRPointTrans.TransPointI2S(point, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); transpoints.Add(transpoint); } UpdateGeometry(transpoints); Outputs[0].UpdateDescription(Outputs[0].Name); feature.UpdateValue(Outputs[0], RoundValue(result.RoiFractalDim, GetResultDigits(PrimaryOutput)), Unit.None); } protected void UpdateGeometry(List outResult) { var geometry = new TraceLineFeature(outResult, RefItem, RefItem.GeoFeature.XUnit, RefItem.GeoFeature.YUnit, false) { IsClosed = true, }; if (RefItem.GeoFeature is ShellTraceFeature feature) { feature.UpdateChildFeatures(new List { geometry }); } } } } public class URMShellDensity : URMShellMeasure { public URMShellDensity(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static URMShellDensity CreateURMShellDensity(ItemMeta meta, IMeasureItem parent) { if (meta.BaseType != MeasureTypes.URMShellDensity) { throw new ArgumentException(); } meta.AddArgs(new MeasureParam(IsAutoSnapKey, "true", DefinitionPriorityEnum.Root)); var item = new URMShellDensity(meta, parent); item.Calculator = new URMShellDensityCal(item); return item; } internal sealed class URMShellDensityCal : Calculator { public URMShellDensityCal(URMShellDensity item) : base(item) { } public URMShellDensityCal() { } protected internal override string[] SupportedOutputKeys { get { return new[] { MeasureTerms.URMDenROI, }; } } protected override void OnCalculate() { if (RefItem.State != ItemStates.Finished) return; PolyLineFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (!isSRDen) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Den)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } if (srcArray.Length != 8 * width * height) { _delayAction.BeginInvoke(); return; } //todo 坐标转换 double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; var points = RefItem.GeoFeature.Points; List ImagePoint = new List(); for (int i = 0; i < points.Count; i++) { var point = SRPointTrans.TransPointS2I(points[i], regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height,false); if (point.X < 0 || point.X > width || point.X < 0 || point.X > width) continue; ImagePoint.Add(point); } if (ImagePoint.Count < 3) return; double pixelscaler = UrmPhysicalwidth / width; var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null) return; var result = urmcal.GetURMShellDenMeasureResult(srcArray.Start, width, height, ImagePoint, RefItem.ShellWidth.Value / 10, pixelscaler, out var outshellPoints); //Todo OutShellPoint调用TransPointI2S转换为逻辑坐标用于绘制 var transpoints = new List(); foreach (var point in outshellPoints) { var transpoint = SRPointTrans.TransPointI2S(point, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); transpoints.Add(transpoint); } UpdateGeometry(transpoints); Outputs[0].UpdateDescription(Outputs[0].Name); feature.UpdateValue(Outputs[0], RoundValue(result.RoiDen * 100, GetResultDigits(PrimaryOutput)), Unit.percent); } protected void UpdateGeometry(List outResult) { var geometry = new TraceLineFeature(outResult, RefItem, RefItem.GeoFeature.XUnit, RefItem.GeoFeature.YUnit, false) { IsClosed = true, }; if (RefItem.GeoFeature is ShellTraceFeature feature) { feature.UpdateChildFeatures(new List { geometry }); } } } } internal class URMShellVelMeasure : URMShellMeasure { public URMShellVelMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static URMShellVelMeasure CreateURMShellVelMeasure(ItemMeta meta, IMeasureItem parent) { if (meta.BaseType != MeasureTypes.URMShellVelMeasure) { throw new ArgumentException(); } meta.AddArgs(new MeasureParam(IsAutoSnapKey, "true", DefinitionPriorityEnum.Root)); var item = new URMShellVelMeasure(meta, parent); item.Calculator = new URMShellVelMeasureCal(item); return item; } internal sealed class URMShellVelMeasureCal : Calculator { public URMShellVelMeasureCal(URMShellVelMeasure item) : base(item) { } public URMShellVelMeasureCal() { } protected internal override string[] SupportedOutputKeys { get { return new[] { MeasureTerms.URMVelMax, MeasureTerms.URMVelMin, MeasureTerms.URMVelMean, MeasureTerms.URMVelStd, MeasureTerms.Area, MeasureTerms.URMVelMaxIn, MeasureTerms.URMVelMinIn, MeasureTerms.URMVelMeanIn, MeasureTerms.URMVelStdIn, MeasureTerms.URMAreaIn, MeasureTerms.URMVelMaxOut, MeasureTerms.URMVelMinOut, MeasureTerms.URMVelMeanOut, MeasureTerms.URMVelStdOut, MeasureTerms.URMAreaOut, }; } } protected override void OnCalculate() { if (RefItem.State != ItemStates.Finished) return; PolyLineFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; double UrmMinVel = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRVel = dicomvisual.isSRVel(); if (!isSRVel) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); UrmMinVel = dicomvisual.GetSRMinVel(); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Vel)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; UrmMinVel = modewithURM.URMMinVel; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } //todo 坐标转换 double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; var points = RefItem.GeoFeature.Points; List ImagePoint = new List(); for (int i = 0; i < points.Count; i++) { var point = SRPointTrans.TransPointS2I(points[i], regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height,false); if (point.X < 0 || point.X > width || point.X < 0 || point.X > width) continue; ImagePoint.Add(point); } if(ImagePoint.Count<3) return; double pixelscaler = UrmPhysicalwidth / width; var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null) return; var result = urmcal.GetURMShellVelMeasureResult(srcArray.Start, width, height, ImagePoint, RefItem.ShellWidth.Value/10, pixelscaler, out var outshellPoints); //Todo OutShellPoint调用TransPointI2S转换为逻辑坐标用于绘制 var transpoints = new List(); foreach (var point in outshellPoints) { var transpoint = SRPointTrans.TransPointI2S(point, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); transpoints.Add(transpoint); } UpdateGeometry(transpoints); foreach (var outputItem in Outputs) { outputItem.UpdateDescription(outputItem.Name); if (string.Equals(outputItem.Name, MeasureTerms.URMVelMax)) { feature.UpdateValue(outputItem, RoundValue(result.MaxVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelMin)) { feature.UpdateValue(outputItem, RoundValue(result.MinVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelMean)) { feature.UpdateValue(outputItem, RoundValue(result.MeanVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelStd)) { feature.UpdateValue(outputItem, RoundValue(Math.Sqrt(result.VarianceVel), outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.Area)) { feature.UpdateValue(outputItem, RoundValue(result.RoiArea, outputItem), Unit.cm2); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelMaxIn)) { feature.UpdateValue(outputItem, RoundValue(result.InMaxVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelMinIn)) { feature.UpdateValue(outputItem, RoundValue(result.InMinVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelMeanIn)) { feature.UpdateValue(outputItem, RoundValue(result.InMeanVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelStdIn)) { feature.UpdateValue(outputItem, RoundValue(Math.Sqrt(result.InVarianceVel), outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMAreaIn)) { feature.UpdateValue(outputItem, RoundValue(result.InRoiArea, outputItem), Unit.cm2); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelMaxOut)) { feature.UpdateValue(outputItem, RoundValue(result.OutMaxVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelMinOut)) { feature.UpdateValue(outputItem, RoundValue(result.OutMinVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelMeanOut)) { feature.UpdateValue(outputItem, RoundValue(result.OutMeanVel + UrmMinVel, outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMVelStdOut)) { feature.UpdateValue(outputItem, RoundValue(Math.Sqrt(result.OutVarianceVel), outputItem), Unit.mms); } else if (string.Equals(outputItem.Name, MeasureTerms.URMAreaOut)) { feature.UpdateValue(outputItem, RoundValue(result.OutRoiArea, outputItem), Unit.cm2); } } } private void UpdateGeometry(List outResult) { //if (outResult.ResultFlag) { //var resultPoints = outResult.OuterShellPoints; // var transformPoints = new List(); // foreach (var point in outResult) // { // transformPoints.Add(RefItem.GeoFeature.HostArea.ViewPort.Convert(point)); // } var geometry = new TraceLineFeature(outResult, RefItem, RefItem.GeoFeature.XUnit, RefItem.GeoFeature.YUnit, false) { IsClosed = true, }; if (RefItem.GeoFeature is ShellTraceFeature feature) { feature.UpdateChildFeatures(new List { geometry }); } } } } } internal class SRTraceMeasure : Trace { private bool calflag = false; public SRTraceMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static SRTraceMeasure CreateSRTraceMeasure(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.SRTraceDensity) { throw new ArgumentException(); } meta.AddArgs(new MeasureParam(IsAutoSnapKey, "true", DefinitionPriorityEnum.Root)); var SRTrace = new SRTraceMeasure(meta, parent); SRTrace.Calculator = new SRTraceCal(SRTrace); return SRTrace; } public override void DownloadValueFromPreviousItem() { } protected override bool OnExecute(PointInfo args) { var cal = Calculator as SRTraceCal; if (args.VisualArea is ISRDicom) { var dicomvisual = args.VisualArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (args.VisualArea.Mode == null || !isSRDen) { return false; } } else { var modewithurm = args.VisualArea.Mode as IModeWithURM; if (modewithurm == null || modewithurm?.URMStyle != "URM(Den)") return false; } calflag = false; cal.calflag = false; var preState = State; var result = base.OnExecute(args); if (result && preState == ItemStates.Running && State == ItemStates.Finished) { calflag = true; cal.calflag = true; } return result; } protected override void OnExecuted(PointInfo args) { if (GeoFeature != null && Calculator != null && calflag) { Calculator.Calculate(); } } internal sealed class SRTraceCal : Calculator { public bool calflag = false; public SRTraceCal(SRTraceMeasure item) : base(item) { } public SRTraceCal() { } protected internal override string[] SupportedOutputKeys { get { return new[] { MeasureTerms.URMDenROI }; } } protected override void OnCalculate() { if (!calflag) return; PolyLineFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (!isSRDen) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Den)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } if (srcArray.Length != 8 * width * height) { _delayAction.BeginInvoke(); return; } //todo 坐标转换 double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; var points = RefItem.GeoFeature.Points; List ImagePoint=new List(); for (int i = 0; i < points.Count; i++) { var point= SRPointTrans.TransPointS2I(points[i], regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); if (point.X < 0 || point.X > width || point.X < 0 || point.X > width) continue; ImagePoint.Add(point); } int outPointsNum = 0; var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null|| ImagePoint.Count<3) return; double roivel = urmcal.GetSRTraceVel(srcArray.Start, width, height, ImagePoint); Outputs[0].UpdateDescription(Outputs[0].Name); feature.UpdateValue(Outputs[0], RoundValue(roivel * 100, GetResultDigits(PrimaryOutput)), Unit.percent); } } } internal class SRROIFractalDimMeasure : Rect { private bool calflag = false; public SRROIFractalDimMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static SRROIFractalDimMeasure CreateSRROIFractalDimMeasure(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.SRROIFractalDim) { throw new ArgumentException(); } var SRROIFractalDim = new SRROIFractalDimMeasure(meta, parent); SRROIFractalDim.Calculator = new SRROIFractalDimCal(SRROIFractalDim); return SRROIFractalDim; } public override void DownloadValueFromPreviousItem() { } protected override bool OnExecute(PointInfo args) { var cal = Calculator as SRROIFractalDimCal; if (args.VisualArea is ISRDicom) { var dicomvisual = args.VisualArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (args.VisualArea.Mode == null || !isSRDen) { return false; } } else { var modewithurm = args.VisualArea.Mode as IModeWithURM; if (modewithurm == null || modewithurm?.URMStyle != "URM(Den)") return false; } calflag = false; cal.calfalg = false; var preState = State; var result = base.OnExecute(args); if (result && preState == ItemStates.Running && State == ItemStates.Finished) { calflag = true; cal.calfalg = true; } return result; } protected override void OnExecuted(PointInfo args) { if (GeoFeature != null && Calculator != null && calflag) { Calculator.Calculate(); } } internal sealed class SRROIFractalDimCal : Calculator { public bool calfalg = false; public SRROIFractalDimCal(SRROIFractalDimMeasure item) : base(item) { } public SRROIFractalDimCal() { } protected internal override string[] SupportedOutputKeys { get { return new[] { MeasureTerms.URMDenFractalDim }; } } protected override void OnCalculate() { if(!calfalg) return; RectFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (!isSRDen) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Den)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } if (srcArray.Length != 8 * width * height) { _delayAction.BeginInvoke(); return; } //todo 坐标转换 double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; DPoint startDPoint = SRPointTrans.TransPointS2I(feature.TopLeft, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); DPoint endDPoint = SRPointTrans.TransPointS2I(feature.BottomRight, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); if (startDPoint.X < 0 || startDPoint.X > width || endDPoint.X < 0 || endDPoint.X > width || startDPoint.Y < 0 || startDPoint.Y > height || endDPoint.Y < 0 || endDPoint.Y > height) return; int outPointsNum = 0; var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null) return; double FractalDimvel = urmcal.GetSRRoiFractalDim(srcArray.Start, width, height, startDPoint.X, startDPoint.Y, endDPoint.X, endDPoint.Y); Outputs[0].UpdateDescription(Outputs[0].Name); feature.UpdateValue(Outputs[0], RoundValue(FractalDimvel, GetResultDigits(PrimaryOutput)), Unit.None); } } } internal class SRROIVelMeasure : Rect { private bool calflag = false; public SRROIVelMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static SRROIVelMeasure CreateSRROIVelMeasure(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.SRRoiVel) { throw new ArgumentException(); } var SRROIVel = new SRROIVelMeasure(meta, parent); SRROIVel.Calculator = new SRRolVelCal(SRROIVel); return SRROIVel; } public override void DownloadValueFromPreviousItem() { } protected override bool OnExecute(PointInfo args) { var cal = Calculator as SRRolVelCal; if (args.VisualArea is ISRDicom) { var dicomvisual = args.VisualArea as ISRDicom; bool isSrVel = dicomvisual.isSRVel(); if (args.VisualArea.Mode == null || !isSrVel) { return false; } } else { var modewithurm = args.VisualArea.Mode as IModeWithURM; if (modewithurm == null || modewithurm?.URMStyle != "URM(Vel)") return false; } calflag = false; cal.calfalg = false; var preState = State; var result = base.OnExecute(args); if (result && preState == ItemStates.Running && State == ItemStates.Finished) { calflag = true; cal.calfalg = true; } return result; } protected override void OnExecuted(PointInfo args) { if (GeoFeature != null && Calculator != null && calflag) { Calculator.Calculate(); } } internal sealed class SRRolVelCal : Calculator { public bool calfalg = false; public SRRolVelCal(SRROIVelMeasure item) : base(item) { } public SRRolVelCal() { } internal static readonly string SRkey = "SRRoiVel"; protected internal override string[] SupportedOutputKeys { get { return new[] { SRkey }; } } protected override void OnCalculate() { if (!calfalg) return; RectFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; double UrmMinVel = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRVel = dicomvisual.isSRVel(); if (!isSRVel) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); UrmMinVel = dicomvisual.GetSRMinVel(); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Vel)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; UrmMinVel = modewithURM.URMMinVel; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } //todo 坐标转换 double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; DPoint startDPoint = SRPointTrans.TransPointS2I(feature.TopLeft, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); DPoint endDPoint = SRPointTrans.TransPointS2I(feature.BottomRight, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); if (startDPoint.X < 0 || startDPoint.X > width || endDPoint.X < 0 || endDPoint.X > width || startDPoint.Y < 0 || startDPoint.Y > height || endDPoint.Y < 0 || endDPoint.Y > height) return; var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null) return; double meanSpeed = urmcal.GetSRRoiSpeed(srcArray.Start, width, height, startDPoint.X, startDPoint.Y, endDPoint.X, endDPoint.Y); meanSpeed += UrmMinVel; feature.UpdateValue(PrimaryOutput, RoundValue(meanSpeed, GetResultDigits(PrimaryOutput)), Unit.mms); } } } internal class SRTraceFractalDimMeasure : Trace { private bool calflag = false; public SRTraceFractalDimMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static SRTraceFractalDimMeasure CreateSRTraceFractalDimMeasure(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.SRTraceFractalDim) { throw new ArgumentException(); } meta.AddArgs(new MeasureParam(IsAutoSnapKey, "true", DefinitionPriorityEnum.Root)); var SRTraceFractalDim = new SRTraceFractalDimMeasure(meta, parent); SRTraceFractalDim.Calculator = new SRTraceFractalDimCal(SRTraceFractalDim); return SRTraceFractalDim; } public override void DownloadValueFromPreviousItem() { } protected override bool OnExecute(PointInfo args) { var cal = Calculator as SRTraceFractalDimCal; if (args.VisualArea is ISRDicom) { var dicomvisual = args.VisualArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (args.VisualArea.Mode == null || !isSRDen) { return false; } } else { var modewithurm = args.VisualArea.Mode as IModeWithURM; if (modewithurm == null || modewithurm?.URMStyle != "URM(Den)") return false; } calflag = false; cal.calflag = false; var preState = State; var result = base.OnExecute(args); if (result && preState == ItemStates.Running && State == ItemStates.Finished) { calflag = true; cal.calflag = true; } return result; } protected override void OnExecuted(PointInfo args) { if (GeoFeature != null && Calculator != null && calflag) { Calculator.Calculate(); } } internal sealed class SRTraceFractalDimCal : Calculator { public bool calflag = false; public SRTraceFractalDimCal(SRTraceFractalDimMeasure item) : base(item) { } public SRTraceFractalDimCal() { } protected internal override string[] SupportedOutputKeys { get { return new[] { MeasureTerms.URMDenFractalDim }; } } protected override void OnCalculate() { if (!calflag) return; PolyLineFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; NativeArray srcArray = new NativeArray(0); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode)//dicom回放 { var dicomvisual = feature.HostArea as ISRDicom; bool isSRDen = dicomvisual.isSRDen(); if (!isSRDen) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); //todo 坐标转换 srcArray.Resize(dicomdate.Length); Marshal.Copy(dicomdate, 0, srcArray.Start, dicomdate.Length); } else if (feature.HostArea.Mode is IModeWithURM)//在URM runing时测量 { var modewithURM = feature.HostArea.Mode as IModeWithURM; if (modewithURM.URMStyle != "URM(Den)") return; var date = modewithURM.UrmArray; width = modewithURM.URMImgWidth; height = modewithURM.URMImgHeight; UrmPhysicalwidth = modewithURM.URMPhyWidth; UrmPhysicalheight = modewithURM.URMPhyHeight; srcArray.Resize(date.Length); Marshal.Copy(date, 0, srcArray.Start, date.Length); } else { return; } if (srcArray.Length != 8 * width * height) { _delayAction.BeginInvoke(); return; } //todo 坐标转换 double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; var points = RefItem.GeoFeature.Points; List ImagePoint = new List(); for (int i = 0; i < points.Count; i++) { var point = SRPointTrans.TransPointS2I(points[i], regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); if (point.X < 0 || point.X > width || point.X < 0 || point.X > width) continue; ImagePoint.Add(point); } int outPointsNum = 0; var urmcal = feature.HostArea.Mode as IURMCal; if (urmcal == null || ImagePoint.Count < 3) return; double roivel = urmcal.GetSRTraceFractalDim(srcArray.Start, width, height, ImagePoint); Outputs[0].UpdateDescription(Outputs[0].Name); feature.UpdateValue(Outputs[0], RoundValue(roivel, GetResultDigits(PrimaryOutput)), Unit.None); } } } public class SRVelMeasure : Location { internal SRVelMeasure(ItemMeta meta, IMeasureItem parent) : base(meta, parent, false) { } // Methods  protected override bool OnExecute(PointInfo args) { if (args.VisualArea is ISRDicom) { var dicomvisual = args.VisualArea as ISRDicom; bool isSRVel = dicomvisual.isSRVel(); if (args.VisualArea.Mode == null || !isSRVel) { return false; } } else { var modewithurm = args.VisualArea.Mode as IModeWithURM; if (modewithurm == null || modewithurm?.URMStyle != "URM(Vel)") return false; } return base.OnExecute(args); } internal static Location CreateSRVelMeasure(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.SRLoactionVel) { throw new ArgumentException(); } SRVelMeasure location = new SRVelMeasure(meta, parent); location.Calculator = new SRVelMeasure.SRVelCal(location); return location; } #region Nested Classes  internal class SRVelCal : LocationCal, IGeoCalculator { #region Properties  protected internal override string[] SupportedOutputKeys { get { return new[] { "SRVel" }; } } #endregion Properties  #region Methods  // Constructors  internal SRVelCal(Location item) : base(item) { } protected internal SRVelCal() { } // Methods  protected override void OnCalculate() { // throw new NotImplementedException(); } public void Calculate(PointInfo pointInfo) { LocationFeature feature = RefItem.GeoFeature; int width = 0; int height = 0; double UrmPhysicalwidth = 0; double UrmPhysicalheight = 0; double UrmMinVel = 0; IntPtr buffer = new IntPtr(); if (feature != null && feature.HostArea is ISRDicom && feature.HostArea.Mode is IDicomMode) { var dicomvisual = feature.HostArea as ISRDicom; bool isSRVel =dicomvisual.isSRVel(); if (!isSRVel) return; var dicomdate = dicomvisual.GetSRDicomFile(ref width, ref height, ref UrmPhysicalwidth, ref UrmPhysicalheight); int size = dicomdate.Length; buffer = Marshal.AllocHGlobal(size); Marshal.Copy(dicomdate, 0, buffer, size); UrmMinVel = dicomvisual.GetSRMinVel(); } else if(feature.HostArea.Mode is IModeWithURM) { var modewithurm = feature.HostArea.Mode as IModeWithURM; if(modewithurm.URMStyle!="URM(Vel)") return; var date = modewithurm.UrmArray; width = modewithurm.URMImgWidth; height = modewithurm.URMImgHeight; UrmPhysicalwidth = modewithurm.URMPhyWidth; UrmPhysicalheight = modewithurm.URMPhyHeight; UrmMinVel = modewithurm.URMMinVel; int size = date.Length; buffer = Marshal.AllocHGlobal(size); Marshal.Copy(date, 0, buffer, size); } else { return; } double regionwidth = feature.HostArea.ViewPort.Region.Width; double regionheight = feature.HostArea.ViewPort.Region.Height; DPoint curPoint = SRPointTrans.TransPointS2I(feature.Point, regionwidth, regionheight, UrmPhysicalwidth, UrmPhysicalheight, width, height); if (curPoint.X < 0 || curPoint.X > width || curPoint.Y < 0 || curPoint.Y > height) return; var curptr = buffer + sizeof(double) * ((int)curPoint.X + (int)curPoint.Y * width); double[] curvel = new double[1]; Marshal.Copy(curptr, curvel, 0, 1); var velvalue = curvel[0]; velvalue += UrmMinVel; if (velvalue < 0.01) velvalue = 0; feature.UpdateValue(PrimaryOutput, RoundValue(velvalue, GetResultDigits(PrimaryOutput)), Unit.mms); } #endregion Methods  } #endregion Nested Classes  } public class URMDen : ProtocolItem { internal URMDen(ItemMeta meta, IMeasureItem parent = null) : base(meta, true, parent) { } internal static URMDen Create(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.URMDen) { throw new ArgumentException(); } var item = new URMDen(meta, parent); item.Calculator = new URMDenCal(item); return item; } internal class URMDenCal : Calculator { protected internal override string[] SupportedOutputKeys => new[] { "URMDen" }; public URMDenCal() { } public URMDenCal(URMDen item) : base(item) { } protected override void OnCalculate() { if (RefItem.Feature != null) { RefItem.Feature.Values.Clear(); if (PrimaryOutput != null) { RefItem.Feature.UpdateValue(PrimaryOutput.Name, new StringValue(PrimaryOutput.Name) { Description = PrimaryOutput.Description }); } } } } } public class URMVel : ProtocolItem { internal URMVel(ItemMeta meta, IMeasureItem parent = null) : base(meta, true, parent) { } internal static URMVel Create(ItemMeta meta, IMeasureItem parent) { if (meta == null || meta.BaseType != MeasureTypes.URMVel) { throw new ArgumentException(); } var item = new URMVel(meta, parent); item.Calculator = new URMVelCal(item); return item; } internal class URMVelCal : Calculator { protected internal override string[] SupportedOutputKeys => new[] { "URMVel" }; public URMVelCal() { } public URMVelCal(URMVel item):base(item) { } protected override void OnCalculate() { if (RefItem.Feature != null) { RefItem.Feature.Values.Clear(); if (PrimaryOutput != null) { RefItem.Feature.UpdateValue(PrimaryOutput.Name, new StringValue(PrimaryOutput.Name) { Description = PrimaryOutput.Description}); } } } } } public class FractalDimSR: URMDensityMeasure { internal FractalDimSR(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static FractalDimSR CreateFractalDimSR(ItemMeta meta, IMeasureItem parent) { if (meta.BaseType != MeasureTypes.FractalDimSR) { throw new ArgumentException(); } var item = new FractalDimSR(meta, parent); return item; } } public class DensitySR : URMDensityMeasure { internal DensitySR(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static DensitySR CreateDensitySR(ItemMeta meta, IMeasureItem parent) { if (meta.BaseType != MeasureTypes.DensitySR) { throw new ArgumentException(); } var item = new DensitySR(meta, parent); return item; } } public class URMDensityMeasure : MultiMethodItem { internal URMDensityMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static URMDensityMeasure CreateURMDensityMeasure(ItemMeta meta, IMeasureItem parent) { if (meta.BaseType != MeasureTypes.URMDensityMeasure) { throw new ArgumentException(); } var item = new URMDensityMeasure(meta, parent); return item; } } public class URMVelMeasure : URMDensityMeasure { internal URMVelMeasure(ItemMeta meta, IMeasureItem parent = null) : base(meta, parent) { } internal static URMVelMeasure CreateURMVelMeasure(ItemMeta meta, IMeasureItem parent) { if (meta.BaseType != MeasureTypes.URMVelMeasure) { throw new ArgumentException(); } var item = new URMVelMeasure(meta, parent); return item; } } }