private static Volume3D <byte> ToVolume3D(
            this ContoursPerSlice contours,
            double spacingX,
            double spacingY,
            double spacingZ,
            Point3D origin,
            Matrix3 direction,
            Region3D <int> roi)
        {
            ContoursPerSlice subContours = new ContoursPerSlice(
                contours.Where(x => x.Value != null).Select(
                    contour =>
                    new KeyValuePair <int, IReadOnlyList <ContourPolygon> >(
                        contour.Key - roi.MinimumZ,
                        contour.Value.Select(x =>
                                             new ContourPolygon(
                                                 x.ContourPoints.Select(
                                                     point => new PointF(point.X - roi.MinimumX, point.Y - roi.MinimumY)).ToArray(), 0))
                        .ToList())).ToDictionary(x => x.Key, y => y.Value));

            var result = new Volume3D <byte>(roi.MaximumX - roi.MinimumX + 1, roi.MaximumY - roi.MinimumY + 1, roi.MaximumZ - roi.MinimumZ + 1, spacingX, spacingY, spacingZ, origin, direction);

            result.Fill(subContours, ModelConstants.MaskForegroundIntensity);

            return(result);
        }
 /// <summary>
 /// Creates a volume that has the same spacing and coordinate system as the reference volume,
 /// and fills all points that fall inside of the contours in the present object with the
 /// default foreground value. The returned volume has its size determined by the given region of interest.
 /// Contour points are transformed using the region of interest.
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="contours">The contours to use for filling.</param>
 /// <param name="refVolume3D">The reference volume to copy spacing and coordinate system from.</param>
 /// <param name="regionOfInterest"></param>
 /// <returns></returns>
 public static Volume3D <byte> ToVolume3D <T>(this ContoursPerSlice contours, Volume3D <T> refVolume3D, Region3D <int> regionOfInterest)
 {
     return(contours.ToVolume3D(
                refVolume3D.SpacingX,
                refVolume3D.SpacingY,
                refVolume3D.SpacingZ,
                refVolume3D.Origin,
                refVolume3D.Direction,
                regionOfInterest));
 }
 /// <summary>
 /// Creates a volume that has the same size, spacing, and coordinate system as the reference volume,
 /// and fills all points that fall inside of the contours in the present object with the default foreground value.
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="contours">The contours to use for filling.</param>
 /// <param name="refVolume3D">The reference volume to copy spacing and coordinate system from.</param>
 /// <returns></returns>
 public static Volume3D <byte> ToVolume3D <T>(this ContoursPerSlice contours, Volume3D <T> refVolume3D)
 {
     return(contours.ToVolume3D(
                refVolume3D.SpacingX,
                refVolume3D.SpacingY,
                refVolume3D.SpacingZ,
                refVolume3D.Origin,
                refVolume3D.Direction,
                refVolume3D.GetFullRegion()));
 }
Пример #4
0
 /// <summary>
 /// Creates a new RadiotherapyContour for inclusion in a RadiotherapyStruct ready for serialization
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="axialContours">The contours relative to the given volume you wish to map into the DICOM reference coordinate system</param>
 /// <param name="identifiers"> The DICOM identifiers describing the origin of the volume</param>
 /// <param name="volumeTransform">The volume transform.</param>
 /// <param name="name">The DICOM structure name</param>
 /// <param name="color">The color of this structure</param>
 /// <param name="roiNumber">The roiNumber of this structure</param>
 /// <returns></returns>
 public static RadiotherapyContour CreateRadiotherapyContour(
     ContoursPerSlice axialContours,
     IReadOnlyList <DicomIdentifiers> identifiers,
     VolumeTransform volumeTransform,
     string name,
     (byte R, byte G, byte B) color,
 /// <summary>
 /// Creates a new instance of the class, setting all properties that the class holds.
 /// </summary>
 /// <param name="name">The name of the anatomical structure that is represented by the contour.</param>
 /// <param name="color">The color that should be used to render the contour.</param>
 /// <param name="contour">The contours broken down by slice of the scan.</param>
 /// <exception cref="ArgumentNullException">The contour name or mask was null.</exception>
 public ContourRenderingInformation(string name, RGBColor color, ContoursPerSlice contour)
 {
     Name    = name ?? throw new ArgumentNullException(nameof(name));
     Color   = color;
     Contour = contour ?? throw new ArgumentNullException(nameof(contour));
 }
 /// <summary>
 /// Modifies the present volume by filling all points that fall inside of the given contours,
 /// using the provided fill value. Contours are filled on axial slices.
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="volume">The volume that should be modified.</param>
 /// <param name="contours">The contours per axial slice.</param>
 /// <param name="value">The value that should be used to fill all points that fall inside of
 /// the given contours.</param>
 public static void Fill <T>(this Volume3D <T> volume, ContoursPerSlice contours, T value)
 => FillPolygon.FillContours(volume, contours, value);
        /// <summary>
        /// Gets the smallest cuboid region that full encloses all the per-slice contours in the present object.
        /// </summary>
        /// <param name="axialContours"></param>
        /// <returns></returns>
        public static Region3D <int> GetRegion(this ContoursPerSlice axialContours)
        {
            var minX = double.MaxValue;
            var maxX = double.MinValue;
            var minY = double.MaxValue;
            var maxY = double.MinValue;
            var minZ = int.MaxValue;
            var maxZ = int.MinValue;

            foreach (var contours in axialContours)
            {
                if (contours.Value.Count == 0)
                {
                    continue;
                }

                if (contours.Key < minZ)
                {
                    minZ = contours.Key;
                }

                if (contours.Key > maxZ)
                {
                    maxZ = contours.Key;
                }

                foreach (var contour in contours.Value)
                {
                    foreach (var point in contour.ContourPoints)
                    {
                        if (point.X < minX)
                        {
                            minX = point.X;
                        }

                        if (point.X > maxX)
                        {
                            maxX = point.X;
                        }

                        if (point.Y < minY)
                        {
                            minY = point.Y;
                        }

                        if (point.Y > maxY)
                        {
                            maxY = point.Y;
                        }
                    }
                }
            }

            minX = minX == double.MaxValue ? 0 : minX;
            minY = minY == double.MaxValue ? 0 : minY;
            minZ = minZ == int.MaxValue ? 0 : minZ;

            maxX = maxX == double.MinValue ? 0 : maxX;
            maxY = maxY == double.MinValue ? 0 : maxY;
            maxZ = maxZ == int.MinValue ? 0 : maxZ;

            return(new Region3D <int>((int)Math.Floor(minX), (int)Math.Floor(minY), minZ, (int)Math.Ceiling(maxX), (int)Math.Ceiling(maxY), maxZ));
        }