/** * Set up the data object with empty UltrasoundPoint%s representing the points * that need to be scanned. * * This is analagous to setting up the view frustum in traditional 3D graphics. */ private void EstablishScanningPlane(ref UltrasoundScanData data) { OnionLogger.globalLog.PushInfoLayer("Pre-populating data"); UltrasoundProbeConfiguration config = data.GetProbeConfig(); // nearZ and farZ represent near and far clipping "planes" (they're really arcs) float nearZ = config.GetMinScanDistance(); float farZ = config.GetMaxScanDistance(); float arcSizeDegrees = config.GetArcSizeInDegrees(); int scanlines = config.GetNumberOfScanlines(); int pointsPerScanline = config.GetPointsPerScanline(); for (int i = 0; i < scanlines; ++i) { UltrasoundScanline scanline = new UltrasoundScanline(config.GetPosition()); float angleInDegrees = -(arcSizeDegrees / 2) + i * arcSizeDegrees / (scanlines - 1); float angleInRadians = Mathf.Deg2Rad * angleInDegrees; Vector2 trajectory = new Vector2(Mathf.Sin(angleInRadians), Mathf.Cos(angleInRadians)); for (int j = 0; j < pointsPerScanline; ++j) { float d = nearZ + j * (farZ - nearZ) / (pointsPerScanline - 1); Vector2 positionOnPlane = d * trajectory; Vector3 positionInWorldSpace = WorldSpaceFromProjectedPosition(positionOnPlane, config); UltrasoundPoint point = new UltrasoundPoint(positionInWorldSpace, positionOnPlane); scanline.AddUltrasoundPoint(point); } data.AddScanline(scanline); } OnionLogger.globalLog.PopInfoLayer(); }
/** * Instantiate a new instance of UltrasoundScanData. * @param config The configuration settings associated with the probe object. */ public UltrasoundScanData(UltrasoundProbeConfiguration config) { #if UNITY_EDITOR UltrasoundDebug.Assert(null != config, "Null config used in constructor", this); #endif this.probeConfig = config; scanlines = new List <UltrasoundScanline>(); }
/** * Based on a probe configuration, determine which organs can possibly appear in the image. * @param scanlines The list of scanlines to be checked. * @param config The current UltrasoundProbeConfiguration * @return A culled list of GameObjects to test for collisions. */ public IList <GameObject> HitableOrgansOnScanlines(IList <UltrasoundScanline> scanlines, UltrasoundProbeConfiguration config) { OnionLogger.globalLog.PushInfoLayer("HORAYOrganCuller"); CheckScanlines(scanlines); RemoveExpiredObjects(); OnionLogger.globalLog.PopInfoLayer(); return(new List <GameObject>(currentVisibleOrgans.Values)); }
/** * Helper method to calculate a Vector3 (WorldSpace) from a Projected Position in local space. * @param positionInPlane A Vector2 representing a point in the scanning plane. * @param config The UltrasoundProbeConfiguration object, used for rotation and translation. * @return A 3D point in world space. */ private Vector3 WorldSpaceFromProjectedPosition(Vector2 positionInPlane, UltrasoundProbeConfiguration config) { Vector3 positionInWorldSpace = new Vector3(positionInPlane.x, 0, positionInPlane.y); // Apply rotation, using Quaternion's overloaded * operator. positionInWorldSpace = config.GetRotation() * positionInWorldSpace; positionInWorldSpace += config.GetPosition(); return(positionInWorldSpace); }
/** * Since the pulse will lose energy after interacting with tissue at a point, we will * need to recalculate the pulse intensity after processing each UltrasoundPoint. * * @param previousPulseIntensity The intensity of the pulse that hit this point. * @param previousOrgan The properties of the organ at this point. * @param config The probe configuration. (Used for normalizing energy loss for higher res display) * * @return The new intensity to use for the next UltrasoundPoint. */ private float PulseIntensityAfterPoint(float previousPulseIntensity, HorayMaterialProperties previousOrgan, UltrasoundProbeConfiguration config) { // When calculating energy lost, we need to normalize for the number of points in the display. float resolutionCoefficient = config.GetPointsPerScanline(); float energyLost = (previousOrgan.echogenicity + previousOrgan.attenuation) / resolutionCoefficient; float newIntensity = previousPulseIntensity - energyLost; return(newIntensity); }
/** * Retrieve the current probe configuration. * @return The UltrasoundProbeConfiguration of the probe GameObject. */ public UltrasoundProbeConfiguration GetProbeConfig() { UltrasoundProbeConfiguration config = new UltrasoundProbeConfiguration(this.transform); config.SetMaxScanDistance(this.MaxDistance); config.SetMinScanDistance(this.MinDistance); config.SetArcSizeInDegrees(this.ArcSizeInDegrees); config.SetNumberOfScanlines(this.NumberOfScanlines); config.SetPointsPerScanline(this.PointsPerScanline); return(config); }
public UltrasoundScanData SendScanData() { OnionLogger.globalLog.PushInfoLayer("HORAYProbeOutput"); UltrasoundProbeConfiguration currentConfig = probeGameObject.GetComponent <HorayBehavior>().GetProbeConfig(); UltrasoundScanData data = new UltrasoundScanData(currentConfig); probe.PopulateData(ref data); OnionLogger.globalLog.PopInfoLayer(); return(data); }
/** * Maps a point in the probe's scanning plane to a pixel index in the image. * @param imageHeight The height of the image being rendered. * @param imageWidth The width of the image being rendered. * @param vector2 The point in the scanning plane to be mapped. * @param probeConfig The UltrasoundProbeConfiguration of the probe object. * @return The corresponding index in the image at which to render the point. */ protected int MapScanningPlaneToPixelCoordinate(int imageHeight, int imageWidth, Vector2 vector2, UltrasoundProbeConfiguration probeConfig) { float pixelsPerWorldUnit = Mathf.Min(imageWidth, imageHeight) / probeConfig.GetMaxScanDistance(); int xCenter = imageWidth / 2; int newX = (int)(xCenter - pixelsPerWorldUnit * vector2.x); int newY = imageHeight - (int)(pixelsPerWorldUnit * vector2.y); int pixelMapping = newY * imageWidth + newX; return(pixelMapping); }
/** * Copy constructor to instantiate a new UltrasoundProbeConfiguration from another. * * @param config The other UltrasoundProbeConfiguration object. * @throw ArgumentNullException */ public UltrasoundProbeConfiguration(UltrasoundProbeConfiguration config) { UltrasoundDebug.Assert(null != config, "Null UltrasoundProbeConfiguration used for copy constructor.", this); this.SetPosition(config.GetPosition()); this.SetRotation(config.GetRotation()); this.maxDistance = config.GetMaxScanDistance(); this.minDistance = config.GetMinScanDistance(); this.arcSizeInDegrees = config.GetArcSizeInDegrees(); this.pointsPerScanline = config.GetPointsPerScanline(); this.numberOfScanlines = config.GetNumberOfScanlines(); this.gain = config.GetGain(); }
public UltrasoundScanData SendScanData() { UltrasoundProbeConfiguration config = new UltrasoundProbeConfiguration(); config.SetMaxScanDistance(MAX_Y); config.SetMinScanDistance(MIN_Y); UltrasoundScanData data = new UltrasoundScanData(config); for (float i = MIN_X; i <= MAX_X; i += STEPSIZE) { UltrasoundScanline scanline = new UltrasoundScanline(config.GetPosition()); for (float j = MIN_Y; j <= MAX_Y; j += STEPSIZE) { UltrasoundPoint p = new UltrasoundPoint(Vector3.zero, new Vector2(i * (j / MAX_Y), j)); p.SetBrightness(Random.Range(0f, 1f)); // Generate noise. scanline.AddUltrasoundPoint(p); } data.AddScanline(scanline); } return(data); }