home *** CD-ROM | disk | FTP | other *** search
/ ftp.hitl.washington.edu / ftp.hitl.washington.edu.tar / ftp.hitl.washington.edu / pub / people / peter / ER / BP_trend.cxx < prev    next >
C/C++ Source or Header  |  1998-07-07  |  25KB  |  885 lines

  1. /*
  2.  BP_trend.cc
  3. */
  4.  
  5. #include "BP_trend.h"
  6.  
  7. #include <iostream.h>
  8. #include <math.h>
  9. //#include <wtpp.h>
  10.  
  11. #include "v3dSystem.h"
  12.  
  13. ///////////////////////////
  14. //    BPTrend        //
  15. /////////////////////////
  16.  
  17. #define REMOBJ    // Remove objects from simulation instead of hiding.
  18. #define NOPERFORMER    // Turn off Performer optimizations.
  19. //#define FRAMERATE    // Print the frame rate at certain intervals.
  20.  
  21. const int BPTrend::Waveform_Tess = 3;    // Tesselation of the waveform objects.
  22. const int BPTrend::Lead_Object_Tess = 4;
  23.                     // Tesselation of the lead object.
  24.  
  25. const int BPTrend::Default_Num_Increments = 80;
  26.                 // Default number of trend increments on an BP trend object.
  27. const int BPTrend::Minimum_Num_Increments = 10;
  28.                 // Minimum number of trend increments on an BP trend object.
  29.  
  30. // Initial colors for the various parts of an BP trend object.
  31. const v3dColor BPTrend::BP_trend_background_color = v3dColor (0, 0, 255);
  32. const v3dColor BPTrend::BP_trend_waveform_color = v3dColor (255, 255, 255);
  33. const v3dColor BPTrend::BP_trend_frame_color = v3dColor (255, 255, 255);
  34. const v3dColor BPTrend::BP_trend_lead_object_color = v3dColor (0, 255, 0);
  35. const v3dColor BPTrend::BP_trend_threshold_color = v3dColor (255, 0, 0);
  36.  
  37. ///////////////
  38. // CREATORS //
  39. /////////////
  40.  
  41. BPTrend::BPTrend (const BPTrend& trend)
  42. {
  43.     initialize (trend.BP_driver_, trend.length_, trend.height_,
  44.         trend.depth_, trend.num_increments_);
  45.  
  46.     paused_ = trend.paused_;
  47.  
  48.     current_x_ = trend.current_x_;
  49.     last_x_ = trend.last_x_;
  50.     last_y_ = trend.last_y_;
  51.     current_index_ = trend.current_index_;
  52.     hide_index_ = trend.hide_index_;
  53.     last_drv_index_ = trend.last_drv_index_;
  54.  
  55.     for (int i = 0; i < num_increments_; ++i)
  56.         plot_values_[i] = trend.plot_values_[i];
  57.  
  58.     MoveAbsolute (trend.GetAbsolutePosition());
  59.     SetAbsoluteOrientation (trend.GetAbsoluteOrientation());
  60. }
  61.  
  62. // BPTrend::Copy()
  63. //    Creates a copy of the trend and returns a pointer to the new trend.
  64. #ifndef SGICC
  65. inline BPTrend*
  66. #else
  67. v3dEntity*
  68. #endif
  69. BPTrend::Copy() const
  70. {
  71.     return new BPTrend (*this);
  72. }
  73.  
  74. ///////////////////
  75. // MANIPULATORS //
  76. /////////////////
  77.  
  78. // BPTrend::initialize
  79. //    Initializer for BPTrend object, called by a BPTrend constructor.
  80. //    Registers this object as a receiver of BP data from an
  81. //    BPDataSender object.
  82. // Parameters:
  83. //    float    length
  84. //            Horizontal extent of the BP trend.
  85. //    float    height
  86. //            Vertical extent of the BP trend.
  87. //    float    depth
  88. //            Thickness of the BP object.
  89. //    int    num_increments
  90. //            Number of increments to show along the length of
  91. //            the trend.
  92. void
  93. BPTrend::initialize (BPTrendDriver    *BP_driver,
  94.     float    length, float height, float depth,
  95.     int    num_increments)
  96. {
  97.     // Assign the BP driver.
  98.     BP_driver_ = BP_driver;
  99.  
  100.     length_ = length;
  101.     height_ = height;
  102.     depth_ = depth;
  103.     num_increments_ = num_increments;
  104.     waveform_radius_ = height_ / 100;
  105.  
  106.     // Calculate trend variables based on the client's specifications.
  107.     calculate_plot_variables();
  108.  
  109.     // Request the range of data from the BP sender object, and calculate
  110.     // the range and scale to be used for the trend.
  111.     data_range_ = BP_driver_->GetDataRange();
  112.     calculate_scale_variables();
  113.  
  114.     // Initialize variables used in determining trendting position.
  115.     current_x_ = increment_length_;
  116.     last_x_ = last_y_ = 0;
  117.     current_index_ = 0;
  118.     last_drv_index_ = 0;
  119.  
  120.     // Register this object's event handler with the BP data sender.
  121.     RegisterEventHandler(BP_driver_, BP_TREND_DATA_UPDATE,
  122.         &BP_update_callback, 0);
  123.  
  124.     paused_ = false;    // The BP trend doesn't start out paused.
  125.  
  126.         // Create the background and frame.
  127.     create_background_and_frame ();
  128.  
  129.     // Create the baseline and other necessary objects.
  130.     create_baseline();
  131. }
  132.  
  133. // BPTrend::Reset
  134. //      Resets the BP trend.  All increments are hidden and the lead object
  135. //      is returned to the origin.
  136. void
  137. BPTrend::Reset()
  138. {
  139.         // Hide the plot line.
  140.         for (int i = 0; i < num_increments_; ++i) {
  141.                 baseline_array_[i]->Disable();
  142.         }
  143.         plot_values_[0] = 0;
  144.         plot_values_[num_increments_-1] = 0;
  145.  
  146.         // Initialize variables used in determining plotting position.
  147.         current_x_ = increment_length_;
  148.         last_x_ = last_y_ = 0;
  149.         current_index_ = 0;
  150.         last_drv_index_ = 0;
  151.  
  152.         // Move the lead object to the origin.
  153.         lead_object_->Move (v3dPos(increment_length_ / 2, 0, 0), *origin_);
  154. }
  155.  
  156. // BPTrend::Pause
  157. //    Pause the update of the BP trend.  No new data will be shown until
  158. //    the trend is unpaused.
  159. void
  160. BPTrend::Pause()
  161. {
  162.     paused_ = true;
  163. // ADD: pausing!
  164. }
  165.  
  166. // BPTrend::Unpause
  167. //    Restart the update of the BP trend.
  168. void
  169. BPTrend::Unpause()
  170. {
  171.     paused_ = false;
  172. // ADD: unpausing!
  173. }
  174.  
  175. // BPTrend::calculate_plot_variables
  176. //    Calculate trend variables based on the client's specifications.
  177. void
  178. BPTrend::calculate_plot_variables()
  179. {
  180.     waveform_radius_ = height_ / 100;
  181.     hide_interval_ = num_increments_ / 8;
  182.     half_depth_ = depth_ / 2;
  183.     lead_object_radius_ = waveform_radius_ * 3;
  184.     frame_width_ = length_ > height_ ? length_ / 40 : height_ / 40;
  185.     background_depth_ = depth_ / 5;
  186.     vert_buffer_ = frame_width_ * 2;
  187.     horiz_buffer_ = length_ / 100;
  188.     baseline_length_ = length_ - 2 * frame_width_ - 2 * horiz_buffer_; 
  189.     baseline_X_ = frame_width_ + horiz_buffer_;
  190.     baseline_Y_ = height_ / 2;
  191.     increment_length_ = baseline_length_ / num_increments_;
  192. }
  193.  
  194. // BPTrend::calculate_scale_variables
  195. //    Calculate the vertical range and scale of the trend based on trend
  196. //    variables and the range of data sent by the BP data sender.
  197. void
  198. BPTrend::calculate_scale_variables()
  199. {
  200.     vert_plot_range_ = height_ - 2 * frame_width_ - 2 * vert_buffer_;
  201. #if 0
  202.     BP_TREND_DATA_TYPE range = data_range_.maximum_value -
  203.         (data_range_.minimum_value > 0 ? 0 : data_range_.minimum_value);
  204. #endif
  205.     BP_TREND_DATA_TYPE range;
  206.     if (fabsf(data_range_.maximum_value) > fabsf(data_range_.minimum_value))
  207.         range = 2 * fabsf(data_range_.maximum_value);
  208.     else
  209.         range = 2 * fabsf(data_range_.minimum_value);
  210.  
  211.     if (range > 0)
  212.         vert_scale_ = vert_plot_range_ / range;
  213.     else
  214.         vert_scale_ = vert_plot_range_;
  215. cerr << "max value: " << data_range_.maximum_value <<
  216.     " min value: " << data_range_.minimum_value <<
  217.     " vert scale: " << vert_scale_ << endl;
  218. }
  219.  
  220. // BPTrend::create_background_and_frame
  221. //    Creates the bounding box, background and frame objects for the BP trend.
  222. void
  223. BPTrend::create_background_and_frame ()
  224. {
  225.     // Create the bounding box that will serve as the root of the object
  226.     // hierarchy for the component objects of the BP.
  227.     bounding_box_ = new v3dBlockObject (length_, height_, depth_);
  228.     bounding_box_->Hide();
  229.  
  230.     // Create the BP object background.
  231.     background_ = new v3dBlockObject (length_, height_, background_depth_);
  232.     background_->MoveAbsolute (v3dPos (0, 0,
  233.                     (depth_ - background_depth_ / 2)));
  234.  
  235.     // The background is initially hidden.
  236.     HideBackground();
  237.  
  238.     // Create the BP object frame.
  239.     frame_bottom_ = new v3dBlockObject (length_, frame_width_, depth_);
  240.     frame_top_ = new v3dBlockObject (length_, frame_width_, depth_);
  241.     frame_left_ = new v3dBlockObject (frame_width_, height_, depth_);
  242.     frame_right_ = new v3dBlockObject (frame_width_, height_, depth_);
  243.  
  244.     frame_bottom_->MoveAbsolute (v3dPos (0, (height_ - frame_width_) / 2,
  245.         0));
  246.     frame_top_->MoveAbsolute (v3dPos (0, (height_ - frame_width_) / -2,
  247.         0));
  248.     frame_left_->MoveAbsolute (v3dPos ((length_ - frame_width_) / -2,
  249.         0, 0));
  250.     frame_right_->MoveAbsolute (v3dPos ((length_ - frame_width_) / 2,
  251.         0, 0));
  252.  
  253.     // Add the frame and the background to the bounding box.
  254.     bounding_box_->Add (background_);
  255.     bounding_box_->Add (frame_bottom_);
  256.     bounding_box_->Add (frame_top_);
  257.     bounding_box_->Add (frame_left_);
  258.     bounding_box_->Add (frame_right_);
  259.  
  260.     // Set the colors of the various elements.
  261.     background_->SetColor(BP_trend_background_color);
  262.     frame_bottom_->SetColor(BP_trend_frame_color);
  263.     frame_top_->SetColor(BP_trend_frame_color);
  264.     frame_left_->SetColor(BP_trend_frame_color);
  265.     frame_right_->SetColor(BP_trend_frame_color);
  266.  
  267. #ifndef NOPERFORMER
  268.     // Specify Performer rendering.
  269.     WTobject_addperformer (
  270.         (WTobject *)background_->GetHandler(),
  271.         FALSE, FALSE, FALSE, FALSE, NULL, NULL);
  272.     WTobject_addperformer (
  273.         (WTobject *)frame_bottom_->GetHandler(),
  274.         FALSE, FALSE, FALSE, FALSE, NULL, NULL);
  275.     WTobject_addperformer (
  276.         (WTobject *)frame_top_->GetHandler(),
  277.         FALSE, FALSE, FALSE, FALSE, NULL, NULL);
  278.     WTobject_addperformer (
  279.         (WTobject *)frame_left_->GetHandler(),
  280.         FALSE, FALSE, FALSE, FALSE, NULL, NULL);
  281.     WTobject_addperformer (
  282.         (WTobject *)frame_right_->GetHandler(),
  283.         FALSE, FALSE, FALSE, FALSE, NULL, NULL);
  284. #endif    // NOPERFORMER
  285.  
  286.     // Set the BP's implementation object to the background's
  287.     // implementation object.
  288.     imp = bounding_box_->GetImplement();
  289.  
  290.     // The frame is initially shown.
  291.     ShowFrame();
  292. }
  293.  
  294. void
  295. BPTrend::scale_background_and_frame(const v3dVector &factors,
  296.     const v3dPos& point)
  297. {
  298. #ifndef NOPERFORMER
  299.     // Temporarirly disable Performer rendering.
  300.     WTobject_deleteperformer ((WTobject *)background_->GetHandler());
  301.     WTobject_deleteperformer ((WTobject *)frame_bottom_->GetHandler());
  302.     WTobject_deleteperformer ((WTobject *)frame_top_->GetHandler());
  303.     WTobject_deleteperformer ((WTobject *)frame_left_->GetHandler());
  304.     WTobject_deleteperformer ((WTobject *)frame_right_->GetHandler());
  305. #endif    // NOPERFORMER
  306.     
  307.     bounding_box_->Scale (factors, point);
  308.     background_->Scale (factors, point);
  309.     frame_top_->Scale (factors, point);
  310.     frame_bottom_->Scale (factors, point);
  311.     frame_left_->Scale (factors, point);
  312.     frame_right_->Scale (factors, point);
  313.  
  314. #ifndef NOPERFORMER
  315.     // Reinstate Performer rendering.
  316.     WTobject_addperformer (
  317.         (WTobject *)background_->GetHandler(),
  318.         FALSE, FALSE, FALSE, FALSE, NULL, NULL);
  319.     WTobject_addperformer (
  320.         (WTobject *)frame_bottom_->GetHandler(),
  321.         FALSE, FALSE, FALSE, FALSE, NULL, NULL);
  322.     WTobject_addperformer (
  323.         (WTobject *)frame_top_->GetHandler(),
  324.         FALSE, FALSE, FALSE, FALSE, NULL, NULL);
  325.     WTobject_addperformer (
  326.         (WTobject *)frame_left_->GetHandler(),
  327.         FALSE, FALSE, FALSE, FALSE, NULL, NULL);
  328.     WTobject_addperformer (
  329.         (WTobject *)frame_right_->GetHandler(),
  330.         FALSE, FALSE, FALSE, FALSE, NULL, NULL);
  331. #endif    // NOPERFORMER
  332. }
  333.  
  334. void
  335. BPTrend::delete_background_and_frame()
  336. {
  337. //    delete bounding_box_;
  338.     delete background_;
  339.     delete frame_left_;
  340.     delete frame_right_;
  341.     delete frame_top_;
  342.     delete frame_bottom_;
  343. }
  344.  
  345. // BPTrend::create_baseline
  346. //    Creates the BP trend's baseline and all objects associated with it.
  347. void
  348. BPTrend::create_baseline()
  349. {
  350.     // Create the baseline origin for the waveform.
  351.     origin_ = new v3dBlockObject (1, 1, 1);
  352.     origin_->MoveAbsolute (v3dVector(baseline_X_ - length_ / 2,
  353.             -baseline_Y_ + height_ / 2, 0));
  354. #ifdef REMOBJ
  355.     origin_->Disable();
  356. #else
  357.     origin_->Hide();
  358. #endif
  359.  
  360.     // Add the baseline origin to the background hierarchy.
  361.     bounding_box_->Add (origin_);
  362.  
  363.     // Create the high and low threshold boundary lines.
  364.     high_threshold_line_ = new v3dCylinderObject (baseline_length_,
  365.                 waveform_radius_, Waveform_Tess);
  366.     low_threshold_line_ = new v3dCylinderObject (baseline_length_,
  367.                 waveform_radius_, Waveform_Tess);
  368.     bounding_box_->Add (high_threshold_line_);
  369.     bounding_box_->Add (low_threshold_line_);
  370.  
  371.     v3dLineObject guide_line (v3dPos(0, 0, 0), v3dPos (1, 0, 0), 
  372.                 waveform_radius_, Waveform_Tess);
  373.     high_threshold_line_->SetOrientation(guide_line.GetAbsoluteOrientation());
  374.     low_threshold_line_->SetOrientation(guide_line.GetAbsoluteOrientation());
  375.     high_threshold_line_->SetColor(BP_trend_threshold_color);
  376.     low_threshold_line_->SetColor(BP_trend_threshold_color);
  377.  
  378.     // Create the lead object.
  379.     float    current_X = baseline_X_ - length_ / 2,
  380.         half_increment = increment_length_ / 2;
  381.  
  382.     lead_object_ = new v3dSphereObject (lead_object_radius_,
  383.         Lead_Object_Tess, Lead_Object_Tess);
  384.     origin_->Add (lead_object_);
  385. //    lead_object_->MoveAbsolute (v3dVector (current_X + half_increment,
  386. //        -baseline_Y_, half_depth_));
  387.         lead_object_->Move (v3dPos(increment_length_ / 2, 0, 0), *origin_);
  388.     lead_object_->SetColor(BP_trend_lead_object_color);
  389. #ifndef NOPERFORMER
  390.     WTobject_addperformer (
  391.         (WTobject *)lead_object_->GetHandler(),
  392.         FALSE, FALSE, FALSE, FALSE, NULL, NULL);
  393. #endif    // NOPERFORMER
  394.  
  395.     // Create the individual baseline trend objects.
  396.     baseline_array_ = new (v3dLineObject *) [num_increments_];
  397.     plot_values_ = new BP_TREND_DATA_TYPE [num_increments_];
  398. //    WTp3    align_vec = { 1, 0, 0 };
  399.     v3dVector    inc_vec (increment_length_, 0, 0);
  400.  
  401. //    v3dPos    from_pos (current_X, -baseline_Y_, half_depth_);
  402.     v3dPos    from_pos (current_X, 0, 0);
  403.  
  404.     for (int ci = 0; ci < num_increments_; ++ci) {
  405.         plot_values_[ci] = 0;
  406.         from_pos.x (current_X);
  407.         baseline_array_[ci]
  408.             = new v3dLineObject (from_pos, from_pos + inc_vec,
  409.                 waveform_radius_, Waveform_Tess);
  410. // CHANGE: this!
  411.         baseline_array_[ci]->SetPoints(*origin_, from_pos, from_pos + inc_vec);
  412. #if 0
  413.         baseline_array_[ci]
  414.             = new v3dLineObject (
  415.                 ((v3dEntity *)origin_)->GetAbsolutePosition(from_pos),
  416.                 ((v3dEntity *)origin_)->GetAbsolutePosition(from_pos + inc_vec),
  417.                 waveform_radius_, Waveform_Tess);
  418. #endif
  419.  
  420.         // Add a baseline trend object to the baseline origin.
  421.         origin_->Add (baseline_array_[ci]);
  422.  
  423. #ifdef REMOBJ
  424.         baseline_array_[ci]->Disable();
  425. #else
  426.         baseline_array_[ci]->Hide();
  427. #endif
  428.  
  429.         // Color the baseline objects.
  430.         baseline_array_[ci]->SetColor(BP_trend_waveform_color);
  431.  
  432.         current_X += increment_length_;
  433.     }
  434.  
  435.     lead_object_->SetColor(BP_trend_lead_object_color);
  436.  
  437.     // Move the threshold lines into place.
  438.     high_threshold_line_->Translate(v3dDir (0,
  439.             - data_range_.high_threshold_value * vert_scale_, 0));
  440.     low_threshold_line_->Translate(v3dDir (0,
  441.             - data_range_.low_threshold_value * vert_scale_, 0));
  442. }
  443.  
  444. void
  445. BPTrend::delete_baseline()
  446. {
  447.     for (int ci = 0; ci < num_increments_; ci++)
  448.         delete baseline_array_[ci];
  449.     delete high_threshold_line_;
  450.     delete low_threshold_line_;
  451.     delete lead_object_;
  452.     delete origin_;
  453. }
  454.  
  455. // BPTrend::BP_update_callback
  456. //    Event handler callback function, notified every cycle to request
  457. //    the latest data from the BP driver.
  458. void
  459. BPTrend::BP_update_callback (const v3dEventMessage *message)
  460. {
  461. #ifdef FRAMERATE
  462.     static int frame_count = 0;
  463.  
  464.     if (++frame_count == 40) {
  465.         cerr << "Frame rate: " << WTuniverse_framerate() << endl;
  466.         frame_count = 0;
  467.     }
  468. #endif    // FRAMERATE
  469.     ((BPTrend *)message->GetEventReceiver())->plot_new_data ();
  470. }
  471.  
  472. // BPTrend::plot_new_data
  473. //    Copies the latest data from the BP driver, then trends any new
  474. //    data on the BP.
  475. void
  476. BPTrend::plot_new_data ()
  477. {
  478.     int current_drv_index = BP_driver_->GetCurrentDataIndex();
  479.  
  480.     // If there's no new data to be displayed, then just return.
  481.     if (last_drv_index_ == current_drv_index)
  482.         return;
  483.  
  484.     int    new_index = current_index_;
  485.     bool    recalculate_hr = false;
  486.  
  487.     // Copy the data from the BP driver.
  488.     do {
  489.         last_drv_index_ =
  490.             BP_driver_->GetNextDataIndex(last_drv_index_);
  491.  
  492.         plot_values_[new_index++] =
  493.                 BP_driver_->data_list[last_drv_index_];
  494.         if (new_index >= num_increments_)
  495.             new_index = 0;
  496.     } while (last_drv_index_ != current_drv_index);
  497.  
  498.     // Plot the new data.
  499.     plot_data (new_index);
  500.  
  501.     current_index_ = new_index;
  502. }
  503.  
  504. // BPTrend::plot_data
  505. //    Plots the BP data on the waveform up to the new index specified.
  506. // Parameters:
  507. //    int new_index
  508. //        The last index of the trend data to be shown.
  509. void
  510. BPTrend::plot_data (int new_index)
  511. {
  512.     float    this_y, diff_y;
  513.     v3dPos    new_pos,
  514.         last_pos = v3dVector(last_x_, -(last_y_), 0);
  515.  
  516.     while (current_index_ != new_index) {
  517.         this_y = plot_values_[current_index_] * vert_scale_;
  518.         diff_y = this_y - last_y_;
  519.         new_pos = v3dVector(current_x_, -(this_y), 0);
  520.  
  521.         hide_index_ = (current_index_ + hide_interval_)
  522.             % num_increments_;
  523.         baseline_array_[hide_index_]->Disable();
  524.  
  525. // cout << "data:" << this_y << " diff: " << diff_y << " ";
  526.  
  527.         baseline_array_[current_index_]->SetPoints(*origin_,
  528.                             last_pos, new_pos);
  529.         baseline_array_[current_index_]->Enable();
  530.  
  531.         // Color the trend.
  532.         baseline_array_[current_index_]->SetColor(
  533.                         BP_trend_waveform_color);
  534.  
  535.         last_y_ = this_y;
  536.         last_pos = new_pos;
  537.         ++current_index_;
  538.         if (current_index_ >= num_increments_) {
  539.             current_index_ = 0;
  540.             current_x_ = increment_length_;
  541.             last_x_ = 0;
  542.             last_pos.x(0);
  543.         } else {
  544.             last_x_ = current_x_;
  545.             current_x_ += increment_length_;
  546.         }
  547.     }
  548.     lead_object_->Move(new_pos);
  549. }
  550.  
  551. void
  552. BPTrend::scale_baseline (const v3dVector &factors, const v3dPos& point)
  553. {
  554.     origin_->Scale(factors, point);
  555.     high_threshold_line_->Scale (factors, point);
  556.     low_threshold_line_->Scale (factors, point);
  557.     // Move the threshold lines into place.
  558.     high_threshold_line_->Move(v3dDir (0,
  559.             - data_range_.high_threshold_value * vert_scale_, 0));
  560.     low_threshold_line_->Move(v3dDir (0,
  561.             - data_range_.low_threshold_value * vert_scale_, 0));
  562.  
  563.     float current_x = increment_length_, last_x = 0;
  564.     float last_y = plot_values_[num_increments_ - 1] * vert_scale_;
  565.  
  566.     for (int i = 0; i < num_increments_; ++i) {
  567.         float    this_y = plot_values_[i] * vert_scale_,
  568.             diff_y = this_y - last_y;
  569. #if 0
  570.         v3dPos    new_pos = origin_->GetAbsolutePosition()
  571.                 + v3dVector(current_x, -(this_y), 0),
  572.             last_pos = origin_->GetAbsolutePosition()
  573.                 + v3dVector(last_x, -(last_y), 0);
  574. #endif
  575.         v3dPos    new_pos = v3dVector(current_x, -(this_y), 0),
  576.             last_pos = v3dVector(last_x, -(last_y), 0);
  577.  
  578.         delete baseline_array_[i];
  579.         baseline_array_[i]
  580.             = new v3dLineObject (last_pos, new_pos,
  581.                 waveform_radius_, Waveform_Tess);
  582.  
  583.         origin_->Add (baseline_array_[i]);
  584. // CHANGE: this!
  585.         baseline_array_[i]->SetPoints(*origin_, last_pos, new_pos);
  586.  
  587. //        baseline_array_[i]->SetPoints(last_pos, new_pos);
  588.         last_x = current_x;
  589.         last_y = this_y;
  590.         current_x += increment_length_;
  591.     }
  592.  
  593.     // Recalculate trendting position variables.
  594. //    last_x_ *= factors.x();
  595. //    current_x_ *= factors.x();
  596. //    if (current_index_ == 0)
  597. //        last_x_ = 0;
  598. //    else
  599.     last_x_ = current_index_ * increment_length_;
  600.     current_x_ = (current_index_+1) * increment_length_;
  601.     last_y_ *= factors.y();
  602. //    last_y_ = plot_values_ [current_index_] * vert_scale_;
  603.  
  604.     delete lead_object_;
  605.     lead_object_ = new v3dSphereObject (lead_object_radius_,
  606.         Lead_Object_Tess, Lead_Object_Tess);
  607.     origin_->Add(lead_object_);
  608.  
  609.     lead_object_->Move(v3dVector(last_x_, -(last_y_), 0));
  610.     lead_object_->SetColor(BP_trend_lead_object_color);
  611. //    lead_object_->Move(origin_->GetAbsolutePosition()
  612. //                + v3dVector(last_x_, -(last_y_), 0));
  613. }
  614.  
  615. // BPTrend::fix_hide_interval
  616. //    Re-hides objects along the hide interval to fix any errors introduced
  617. //    when the sweep speed was changed.
  618. void
  619. BPTrend::fix_hide_interval ()
  620. {
  621.     hide_interval_ = num_increments_ / 8;
  622.  
  623.     int    current_index = current_index_;
  624.     for (int i = 0; i < hide_interval_; ++i, ++current_index) {
  625.         if (current_index >= num_increments_)
  626.             current_index = 0;
  627. #ifdef REMOBJ
  628.         baseline_array_[current_index]->Disable();
  629. #else
  630.         baseline_array_[current_index]->Hide();
  631. #endif
  632.     }
  633. }
  634.  
  635. // BPTrend::extend_baseline
  636. //    Extends the baseline to the number of increments specified.
  637. //    The old baseline array is copied to a new baseline array, and the
  638. //    new elements in the array are initialized with flat baseline
  639. //    elements.
  640. // Parameters:
  641. //    unsigned int    old_increment_num
  642. //        Old number of increments on the the baseline.
  643. //    unsigned int    new_increment_num
  644. //        New number of increments on the the baseline.
  645. void
  646. BPTrend::extend_baseline (unsigned int old_increment_num,
  647.     unsigned int new_increment_num)
  648. {
  649.     ASSERT (new_increment_num >= old_increment_num);
  650.  
  651.     v3dLineObject    **new_baseline_array
  652.         = new (v3dLineObject *) [new_increment_num];
  653.     BP_TREND_DATA_TYPE    *new_plot_values
  654.         = new BP_TREND_DATA_TYPE [new_increment_num];
  655.  
  656.     // Copy the old baseline elements into the new array.
  657.     for (int i = 0; i < old_increment_num; ++i) {
  658.         new_baseline_array[i] = baseline_array_[i];
  659.         new_plot_values [i] = plot_values_ [i];
  660.     }
  661.     delete [] baseline_array_;
  662.     delete [] plot_values_;
  663.  
  664.     // Create new, flat baseline objects.
  665.     v3dVector    inc_vec (increment_length_, 0, 0);
  666.     float    current_X = old_increment_num * increment_length_;
  667.  
  668.     v3dPos    from_pos (current_X, 0, 0);
  669. //    v3dPos    from_pos (current_X, -baseline_Y_, half_depth_);
  670.  
  671.     for (int ci = old_increment_num; ci < new_increment_num; ++ci) {
  672.         new_plot_values[ci] = 0;
  673.         from_pos.x (current_X);
  674. #if 0
  675.         new_baseline_array[ci]
  676.             = new v3dLineObject (
  677.                 ((v3dEntity *)origin_)->GetAbsolutePosition(from_pos),
  678.                 ((v3dEntity *)origin_)->GetAbsolutePosition(from_pos + inc_vec),
  679.                 waveform_radius_, Waveform_Tess);
  680. #endif
  681.         new_baseline_array[ci]
  682.             = new v3dLineObject (from_pos, from_pos + inc_vec,
  683.                 waveform_radius_, Waveform_Tess);
  684. // CHANGE: this!
  685.         new_baseline_array[ci]->SetPoints(*origin_, from_pos, from_pos + inc_vec);
  686.  
  687.         // Add a baseline trend object to the baseline origin.
  688.         origin_->Add (new_baseline_array[ci]);
  689.  
  690. #if 0
  691. #ifdef REMOBJ
  692.         new_baseline_array[ci]->Disable();
  693. #else
  694.         new_baseline_array[ci]->Hide();
  695. #endif
  696. #endif
  697.  
  698.         // Color the baseline objects.
  699.         new_baseline_array[ci]->SetColor(BP_trend_waveform_color);
  700.  
  701.         current_X += increment_length_;
  702.     }
  703.  
  704.     baseline_array_ = new_baseline_array;
  705.     plot_values_ = new_plot_values;
  706. }
  707.  
  708. // BPTrend::shrink_baseline
  709. //    Shrinks the baseline to the number of increments specified.
  710. //    The old baseline array is copied to a new baseline array, leaving
  711. //    out extra elements farthest from the leading edge of the graph.
  712. // Parameters:
  713. //    unsigned int    old_increment_num
  714. //        Old number of increments on the the baseline.
  715. //    unsigned int    new_increment_num
  716. //        New number of increments on the the baseline.
  717. void
  718. BPTrend::shrink_baseline (unsigned int old_increment_num,
  719.     unsigned int new_increment_num)
  720. {
  721.     ASSERT (new_increment_num <= old_increment_num);
  722.  
  723.     v3dLineObject    **new_baseline_array
  724.         = new (v3dLineObject *) [new_increment_num];
  725.     BP_TREND_DATA_TYPE    *new_plot_values
  726.         = new BP_TREND_DATA_TYPE [new_increment_num];
  727.  
  728.     // Copy the old baseline elements into the new array.
  729.     int    start_index, finish_index;
  730.     if (current_index_ >= new_increment_num) {
  731.         start_index = current_index_ - new_increment_num + 1;
  732.         finish_index = current_index_ + 1;
  733.         current_index_ = new_increment_num - 1;
  734.         current_x_ = current_index_ * increment_length_;
  735.         last_x_ = (current_index_-1) * increment_length_;
  736.     } else {
  737.         start_index = 0;
  738.         finish_index = new_increment_num;
  739.     }
  740.     for (int i = 0; i < start_index; ++i)
  741.         delete baseline_array_[i];
  742.     for (int i = start_index; i < finish_index; ++i) {
  743.         new_baseline_array[i-start_index] = baseline_array_[i];
  744.         new_plot_values [i-start_index] = plot_values_ [i];
  745.     }
  746.     for (int i = finish_index; i < old_increment_num; ++i)
  747.         delete baseline_array_[i];
  748.  
  749.     delete [] baseline_array_;
  750.     delete [] plot_values_;
  751.  
  752.     baseline_array_ = new_baseline_array;
  753.     plot_values_ = new_plot_values;
  754. }
  755.  
  756. // BPTrend::MoveFrontLowerLeftCorner
  757. //    Move the entire BP trend.
  758. // Parameters:
  759. //    v3dPos&    pos
  760. //            New location for the front lower left corner.
  761. void
  762. BPTrend::MoveFrontLowerLeftCorner (const v3dPos& pos)
  763. {
  764.     GetObject()->MoveAbsolute (v3dVector (pos.x() + length_ / 2,
  765.         pos.y() - height_ / 2,
  766.         pos.z() + depth_ / 2));
  767. }
  768.  
  769. void
  770. BPTrend::HideFrame ()
  771. {
  772.     frame_left_->Hide();
  773.     frame_right_->Hide();
  774.     frame_top_->Hide();
  775.     frame_bottom_->Hide();
  776.     frame_hidden_ = true;
  777. }
  778.  
  779. void
  780. BPTrend::ShowFrame ()
  781. {
  782.     frame_left_->Show();
  783.     frame_right_->Show();
  784.     frame_top_->Show();
  785.     frame_bottom_->Show();
  786.     frame_hidden_ = false;
  787. }
  788.  
  789. // BPTrend::Scale
  790. //    Stretches the BP trend about a point by the given factors.
  791. void
  792. BPTrend::Scale (const v3dVector &factors, const v3dPos& point)
  793. {
  794.     scale_background_and_frame(factors, point);
  795.  
  796.     v3dDim dim = bounding_box_->GetSize();
  797.     length_ = dim.x();
  798.     height_ = dim.y();
  799.     depth_ = dim.z();
  800.  
  801.     calculate_plot_variables();
  802.     calculate_scale_variables();
  803.  
  804.     scale_baseline(factors, point);
  805.  
  806.     fix_hide_interval();
  807. }
  808.  
  809. // BPTrend::SetSize
  810. //    Sets the exact size of the BP.
  811. inline void
  812. BPTrend::SetSize (const v3dDim &dimensions)
  813. {
  814.     Scale (v3dVector (dimensions.x() / length_,
  815.         dimensions.y() / height_,
  816.         dimensions.z() / depth_));
  817. }
  818.  
  819. // BPTrend::ChangeSweepSpeed
  820. //    Increases or decreases the sweep speed of the BP trend by the
  821. //    specified factor.
  822. //    The number of increments on the baseline is either increased or
  823. //    decreased, and the baseline as a whole is scaled up or down.
  824. // Parameters:
  825. //    float    change_factor
  826. //            Factor to change the speed by.  For example,
  827. //                1 = no change,
  828. //                1.05 = 5% faster,
  829. //                0.95 = 5% slower
  830. void
  831. BPTrend::ChangeSweepSpeed (float change_factor)
  832. {
  833.     int new_num_increments = (int)trunc (num_increments_ * change_factor);
  834.     if (new_num_increments < Minimum_Num_Increments)
  835.         new_num_increments = Minimum_Num_Increments;
  836.  
  837.     if (change_factor > 1)
  838.         extend_baseline (num_increments_, new_num_increments);
  839.     else
  840.         shrink_baseline (num_increments_, new_num_increments);
  841.     num_increments_ = new_num_increments;
  842.  
  843.     increment_length_ = baseline_length_ / new_num_increments;
  844.     scale_baseline (v3dVector (1/change_factor, 1, 1),
  845.                 origin_->GetAbsolutePosition());
  846.  
  847.     fix_hide_interval();
  848. }
  849.  
  850. // BPTrend::~BPTrend
  851. BPTrend::~BPTrend ()
  852. {
  853.     delete_baseline();
  854.     delete_background_and_frame();
  855. }
  856.  
  857. void
  858. BPTrend::switch_data ()
  859. {
  860.     last_drv_index_ = 0;
  861.     data_range_ = BP_driver_->GetDataRange();
  862.     calculate_scale_variables();
  863. }
  864.  
  865. bool
  866. BPTrend::CorrectUp()
  867. {
  868.     if (BP_driver_->CorrectUp()) {
  869.         last_drv_index_ = 0;
  870.         return true;
  871.     } else
  872.         return false;
  873. }
  874.  
  875. bool
  876. BPTrend::CorrectDown()
  877. {
  878.     if (BP_driver_->CorrectDown()) {
  879.         last_drv_index_ = 0;
  880.         return true;
  881.     } else
  882.         return false;
  883. }
  884.  
  885.