/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkCubeAxesActor2D.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkCubeAxesActor2D.h" #include "vtkAxisActor2D.h" #include "vtkCamera.h" #include "vtkDataSet.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkTextProperty.h" #include "vtkViewport.h" vtkCxxRevisionMacro(vtkCubeAxesActor2D, "$Revision: 1.52.10.1 $"); vtkStandardNewMacro(vtkCubeAxesActor2D); vtkCxxSetObjectMacro(vtkCubeAxesActor2D,Input, vtkDataSet); vtkCxxSetObjectMacro(vtkCubeAxesActor2D,Camera,vtkCamera); vtkCxxSetObjectMacro(vtkCubeAxesActor2D,ViewProp,vtkProp); vtkCxxSetObjectMacro(vtkCubeAxesActor2D,AxisLabelTextProperty,vtkTextProperty); vtkCxxSetObjectMacro(vtkCubeAxesActor2D,AxisTitleTextProperty,vtkTextProperty); //---------------------------------------------------------------------------- // Instantiate this object. vtkCubeAxesActor2D::vtkCubeAxesActor2D() { this->Input = NULL; this->ViewProp = NULL; this->Bounds[0] = -1.0; this->Bounds[1] = 1.0; this->Bounds[2] = -1.0; this->Bounds[3] = 1.0; this->Bounds[4] = -1.0; this->Bounds[5] = 1.0; this->UseRanges = 0; this->Ranges[0] = 0; this->Ranges[1] = 0; this->Ranges[2] = 0; this->Ranges[3] = 0; this->Ranges[4] = 0; this->Ranges[5] = 0; this->Camera = NULL; this->FlyMode = VTK_FLY_CLOSEST_TRIAD; this->Scaling = 1; this->XAxis = vtkAxisActor2D::New(); this->XAxis->GetPositionCoordinate()->SetCoordinateSystemToDisplay(); this->XAxis->GetPosition2Coordinate()->SetCoordinateSystemToDisplay(); this->XAxis->AdjustLabelsOff(); this->YAxis = vtkAxisActor2D::New(); this->YAxis->GetPositionCoordinate()->SetCoordinateSystemToDisplay(); this->YAxis->GetPosition2Coordinate()->SetCoordinateSystemToDisplay(); this->YAxis->AdjustLabelsOff(); this->ZAxis = vtkAxisActor2D::New(); this->ZAxis->GetPositionCoordinate()->SetCoordinateSystemToDisplay(); this->ZAxis->GetPosition2Coordinate()->SetCoordinateSystemToDisplay(); this->ZAxis->AdjustLabelsOff(); this->NumberOfLabels = 3; this->AxisLabelTextProperty = vtkTextProperty::New(); this->AxisLabelTextProperty->SetBold(1); this->AxisLabelTextProperty->SetItalic(1); this->AxisLabelTextProperty->SetShadow(1); this->AxisLabelTextProperty->SetFontFamilyToArial(); this->AxisTitleTextProperty = vtkTextProperty::New(); this->AxisTitleTextProperty->ShallowCopy(this->AxisLabelTextProperty); this->LabelFormat = new char[8]; sprintf(this->LabelFormat,"%s","%-#6.3g"); this->FontFactor = 1.0; this->CornerOffset = 0.05; this->Inertia = 1; this->ShowActualBounds = 1; this->RenderCount = 0; this->XAxisVisibility = 1; this->YAxisVisibility = 1; this->ZAxisVisibility = 1; this->XLabel = new char[2]; sprintf(this->XLabel,"%s","X"); this->YLabel = new char[2]; sprintf(this->YLabel,"%s","Y"); this->ZLabel = new char[2]; sprintf(this->ZLabel,"%s","Z"); } //---------------------------------------------------------------------------- // Shallow copy of an actor. void vtkCubeAxesActor2D::ShallowCopy(vtkCubeAxesActor2D *actor) { this->vtkActor2D::ShallowCopy(actor); this->SetAxisLabelTextProperty(actor->GetAxisLabelTextProperty()); this->SetAxisTitleTextProperty(actor->GetAxisTitleTextProperty()); this->SetLabelFormat(actor->GetLabelFormat()); this->SetFontFactor(actor->GetFontFactor()); this->SetCornerOffset(actor->GetCornerOffset()); this->SetInertia(static_cast(actor->GetInertia())); this->SetXLabel(actor->GetXLabel()); this->SetYLabel(actor->GetYLabel()); this->SetZLabel(actor->GetZLabel()); this->SetFlyMode(actor->GetFlyMode()); this->SetInput(actor->GetInput()); this->SetViewProp(actor->GetViewProp()); this->SetCamera(actor->GetCamera()); } //---------------------------------------------------------------------------- vtkCubeAxesActor2D::~vtkCubeAxesActor2D() { if ( this->Input ) { this->Input->Delete(); } if ( this->ViewProp ) { this->ViewProp->Delete(); } if ( this->Camera ) { this->Camera->UnRegister(this); } this->XAxis->Delete(); this->YAxis->Delete(); this->ZAxis->Delete(); if (this->LabelFormat) { delete [] this->LabelFormat; this->LabelFormat = NULL; } if ( this->XLabel ) { delete [] this->XLabel; } if ( this->YLabel ) { delete [] this->YLabel; } if ( this->ZLabel ) { delete [] this->ZLabel; } this->SetAxisLabelTextProperty(NULL); this->SetAxisTitleTextProperty(NULL); } //---------------------------------------------------------------------------- // Static variable describes connections in cube. static int Conn[8][3] = {{1,2,4}, {0,3,5}, {3,0,6}, {2,1,7}, {5,6,0}, {4,7,1}, {7,4,2}, {6,5,3}}; //---------------------------------------------------------------------------- // Project the bounding box and compute edges on the border of the bounding // cube. Determine which parts of the edges are visible via intersection // with the boundary of the viewport (minus borders). int vtkCubeAxesActor2D::RenderOverlay(vtkViewport *viewport) { int renderedSomething=0; // Initialization if ( ! this->RenderSomething ) { return 0; } //Render the axes if ( this->XAxisVisibility ) { renderedSomething += this->XAxis->RenderOverlay(viewport); } if ( this->YAxisVisibility ) { renderedSomething += this->YAxis->RenderOverlay(viewport); } if ( this->ZAxisVisibility ) { renderedSomething += this->ZAxis->RenderOverlay(viewport); } return renderedSomething; } //---------------------------------------------------------------------------- // Project the bounding box and compute edges on the border of the bounding // cube. Determine which parts of the edges are visible via intersection // with the boundary of the viewport (minus borders). int vtkCubeAxesActor2D::RenderOpaqueGeometry(vtkViewport *viewport) { double bounds[6]; double slope = 0.0, minSlope, num, den; double pts[8][3], d2, d2Min, min; int i, idx = 0; int xIdx, yIdx = 0, zIdx = 0, zIdx2, renderedSomething=0; int xAxes = 0, yAxes, zAxes; // Initialization if ( !this->Camera ) { vtkErrorMacro(<<"No camera!"); this->RenderSomething = 0; return 0; } this->RenderSomething = 1; // determine the bounds to use this->GetBounds(bounds); // Build the axes (almost always needed so we don't check mtime) // Transform all points into display coordinates this->TransformBounds(viewport, bounds, pts); // Find the portion of the bounding box that fits within the viewport, if ( !this->ShowActualBounds && (this->ClipBounds(viewport, pts, bounds) == 0) ) { this->RenderSomething = 0; return 0; } // Take into account the inertia. Process only so often. if ( this->RenderCount++ == 0 || !(this->RenderCount % this->Inertia) ) { // Okay, we have a bounding box, maybe clipped and scaled, that is visible. // We setup the axes depending on the fly mode. if ( this->FlyMode == VTK_FLY_CLOSEST_TRIAD ) { // Loop over points and find the closest point to the camera min = VTK_DOUBLE_MAX; for (i=0; i < 8; i++) { if ( pts[i][2] < min ) { idx = i; min = pts[i][2]; } } // Setup the three axes to be drawn xAxes = 0; xIdx = Conn[idx][0]; yAxes = 1; yIdx = Conn[idx][1]; zAxes = 2; zIdx = idx; zIdx2 = Conn[idx][2]; } else { double e1[2], e2[2], e3[2]; // Find distance to origin d2Min = VTK_DOUBLE_MAX; for (i=0; i < 8; i++) { d2 = pts[i][0]*pts[i][0] + pts[i][1]*pts[i][1]; if ( d2 < d2Min ) { d2Min = d2; idx = i; } } // find minimum slope point connected to closest point and on // right side (in projected coordinates). This is the first edge. minSlope = VTK_DOUBLE_MAX; for (xIdx=0, i=0; i<3; i++) { num = (pts[Conn[idx][i]][1] - pts[idx][1]); den = (pts[Conn[idx][i]][0] - pts[idx][0]); if ( den != 0.0 ) { slope = num / den; } if ( slope < minSlope && den > 0 ) { xIdx = Conn[idx][i]; yIdx = Conn[idx][(i+1)%3]; zIdx = Conn[idx][(i+2)%3]; xAxes = i; minSlope = slope; } } // find edge (connected to closest point) on opposite side for ( i=0; i<2; i++) { e1[i] = (pts[xIdx][i] - pts[idx][i]); e2[i] = (pts[yIdx][i] - pts[idx][i]); e3[i] = (pts[zIdx][i] - pts[idx][i]); } vtkMath::Normalize2D(e1); vtkMath::Normalize2D(e2); vtkMath::Normalize2D(e3); if ( vtkMath::Dot2D(e1,e2) < vtkMath::Dot2D(e1,e3) ) { yAxes = (xAxes + 1) % 3; } else { yIdx = zIdx; yAxes = (xAxes + 2) % 3; } // Find the final point by determining which global x-y-z axes have not // been represented, and then determine the point closest to the viewer. zAxes = (xAxes != 0 && yAxes != 0 ? 0 : (xAxes != 1 && yAxes != 1 ? 1 : 2)); if ( pts[Conn[xIdx][zAxes]][2] < pts[Conn[yIdx][zAxes]][2] ) { zIdx = xIdx; zIdx2 = Conn[xIdx][zAxes]; } else { zIdx = yIdx; zIdx2 = Conn[yIdx][zAxes]; } }//else boundary edges fly mode this->InertiaAxes[0] = idx; this->InertiaAxes[1] = xIdx; this->InertiaAxes[2] = yIdx; this->InertiaAxes[3] = zIdx; this->InertiaAxes[4] = zIdx2; this->InertiaAxes[5] = xAxes; this->InertiaAxes[6] = yAxes; this->InertiaAxes[7] = zAxes; } //inertia else { idx = this->InertiaAxes[0]; xIdx = this->InertiaAxes[1]; yIdx = this->InertiaAxes[2]; zIdx = this->InertiaAxes[3]; zIdx2 = this->InertiaAxes[4]; xAxes = this->InertiaAxes[5]; yAxes = this->InertiaAxes[6]; zAxes = this->InertiaAxes[7]; } // Setup the axes for plotting double xCoords[4], yCoords[4], zCoords[4], xRange[2], yRange[2], zRange[2]; this->AdjustAxes(pts, bounds, idx, xIdx, yIdx, zIdx, zIdx2, xAxes, yAxes, zAxes, xCoords, yCoords, zCoords, xRange, yRange, zRange); // Sorry for ugly hack. I find the fonts slightly too large on the axis. BNW double AxisFontFactor = this->FontFactor*.75; // Upate axes this->Labels[0] = this->XLabel; this->Labels[1] = this->YLabel; this->Labels[2] = this->ZLabel; this->XAxis->GetPositionCoordinate()->SetValue(xCoords[0], xCoords[1]); this->XAxis->GetPosition2Coordinate()->SetValue(xCoords[2], xCoords[3]); this->XAxis->SetRange(xRange[0], xRange[1]); this->XAxis->SetTitle(this->Labels[xAxes]); this->XAxis->SetNumberOfLabels(this->NumberOfLabels); this->XAxis->SetLabelFormat(this->LabelFormat); this->XAxis->SetFontFactor(AxisFontFactor); this->XAxis->SetProperty(this->GetProperty()); this->YAxis->GetPositionCoordinate()->SetValue(yCoords[2], yCoords[3]); this->YAxis->GetPosition2Coordinate()->SetValue(yCoords[0], yCoords[1]); this->YAxis->SetRange(yRange[1], yRange[0]); this->YAxis->SetTitle(this->Labels[yAxes]); this->YAxis->SetNumberOfLabels(this->NumberOfLabels); this->YAxis->SetLabelFormat(this->LabelFormat); this->YAxis->SetFontFactor(AxisFontFactor); this->YAxis->SetProperty(this->GetProperty()); this->ZAxis->GetPositionCoordinate()->SetValue(zCoords[0], zCoords[1]); this->ZAxis->GetPosition2Coordinate()->SetValue(zCoords[2], zCoords[3]); this->ZAxis->SetRange(zRange[0], zRange[1]); this->ZAxis->SetTitle(this->Labels[zAxes]); this->ZAxis->SetNumberOfLabels(this->NumberOfLabels); this->ZAxis->SetLabelFormat(this->LabelFormat); this->ZAxis->SetFontFactor(AxisFontFactor); this->ZAxis->SetProperty(this->GetProperty()); // Rebuid text props // Perform shallow copy here since each individual axis can be // accessed through the class API (i.e. each individual axis text prop // can be changed). Therefore, we can not just assign pointers otherwise // each individual axis text prop would point to the same text prop. if (this->AxisLabelTextProperty && this->AxisLabelTextProperty->GetMTime() > this->BuildTime) { if (this->XAxis->GetLabelTextProperty()) { this->XAxis->GetLabelTextProperty()->ShallowCopy( this->AxisLabelTextProperty); } if (this->YAxis->GetLabelTextProperty()) { this->YAxis->GetLabelTextProperty()->ShallowCopy( this->AxisLabelTextProperty); } if (this->ZAxis->GetLabelTextProperty()) { this->ZAxis->GetLabelTextProperty()->ShallowCopy( this->AxisLabelTextProperty); } } if (this->AxisTitleTextProperty && this->AxisTitleTextProperty->GetMTime() > this->BuildTime) { if (this->XAxis->GetLabelTextProperty()) { this->XAxis->GetTitleTextProperty()->ShallowCopy( this->AxisTitleTextProperty); } if (this->YAxis->GetLabelTextProperty()) { this->YAxis->GetTitleTextProperty()->ShallowCopy( this->AxisTitleTextProperty); } if (this->ZAxis->GetLabelTextProperty()) { this->ZAxis->GetTitleTextProperty()->ShallowCopy( this->AxisTitleTextProperty); } } this->BuildTime.Modified(); //Render the axes if ( this->XAxisVisibility ) { renderedSomething += this->XAxis->RenderOpaqueGeometry(viewport); } if ( this->YAxisVisibility ) { renderedSomething += this->YAxis->RenderOpaqueGeometry(viewport); } if ( this->ZAxisVisibility ) { renderedSomething += this->ZAxis->RenderOpaqueGeometry(viewport); } return renderedSomething; } //---------------------------------------------------------------------------- // Do final adjustment of axes to control offset, etc. void vtkCubeAxesActor2D::AdjustAxes(double pts[8][3], double bounds[6], int idx, int xIdx, int yIdx, int zIdx, int zIdx2, int xAxes, int yAxes, int zAxes, double xCoords[4], double yCoords[4], double zCoords[4], double xRange[2], double yRange[2], double zRange[2]) { double *internal_bounds; if ( this->UseRanges ) { internal_bounds = this->Ranges; } else { internal_bounds = bounds; } // The x-axis xCoords[0] = pts[idx][0]; xCoords[1] = pts[idx][1]; xCoords[2] = pts[xIdx][0]; xCoords[3] = pts[xIdx][1]; if ( idx < xIdx ) { xRange[0] = internal_bounds[2*xAxes]; xRange[1] = internal_bounds[2*xAxes+1]; } else { xRange[0] = internal_bounds[2*xAxes+1]; xRange[1] = internal_bounds[2*xAxes]; } // The y-axis yCoords[0] = pts[idx][0]; yCoords[1] = pts[idx][1]; yCoords[2] = pts[yIdx][0]; yCoords[3] = pts[yIdx][1]; if ( idx < yIdx ) { yRange[0] = internal_bounds[2*yAxes]; yRange[1] = internal_bounds[2*yAxes+1]; } else { yRange[0] = internal_bounds[2*yAxes+1]; yRange[1] = internal_bounds[2*yAxes]; } // The z-axis if ( zIdx != xIdx && zIdx != idx ) //rearrange for labels { zIdx = zIdx2; zIdx2 = yIdx; } zCoords[0] = pts[zIdx][0]; zCoords[1] = pts[zIdx][1]; zCoords[2] = pts[zIdx2][0]; zCoords[3] = pts[zIdx2][1]; if ( zIdx < zIdx2 ) { zRange[0] = internal_bounds[2*zAxes]; zRange[1] = internal_bounds[2*zAxes+1]; } else { zRange[0] = internal_bounds[2*zAxes+1]; zRange[1] = internal_bounds[2*zAxes]; } // Pull back the corners if specified if ( this->CornerOffset > 0.0 ) { double ave; // x-axis ave = (xCoords[0] + xCoords[2]) / 2.0; xCoords[0] = xCoords[0] - this->CornerOffset * (xCoords[0] - ave); xCoords[2] = xCoords[2] - this->CornerOffset * (xCoords[2] - ave); ave = (xCoords[1] + xCoords[3]) / 2.0; xCoords[1] = xCoords[1] - this->CornerOffset * (xCoords[1] - ave); xCoords[3] = xCoords[3] - this->CornerOffset * (xCoords[3] - ave); ave = (xRange[1] + xRange[0]) / 2.0; if (!this->ShowActualBounds) { xRange[0] = xRange[0] - this->CornerOffset * (xRange[0] - ave); xRange[1] = xRange[1] - this->CornerOffset * (xRange[1] - ave); } // y-axis ave = (yCoords[0] + yCoords[2]) / 2.0; yCoords[0] = yCoords[0] - this->CornerOffset * (yCoords[0] - ave); yCoords[2] = yCoords[2] - this->CornerOffset * (yCoords[2] - ave); ave = (yCoords[1] + yCoords[3]) / 2.0; yCoords[1] = yCoords[1] - this->CornerOffset * (yCoords[1] - ave); yCoords[3] = yCoords[3] - this->CornerOffset * (yCoords[3] - ave); ave = (yRange[1] + yRange[0]) / 2.0; if (!this->ShowActualBounds) { yRange[0] = yRange[0] - this->CornerOffset * (yRange[0] - ave); yRange[1] = yRange[1] - this->CornerOffset * (yRange[1] - ave); } // z-axis ave = (zCoords[0] + zCoords[2]) / 2.0; zCoords[0] = zCoords[0] - this->CornerOffset * (zCoords[0] - ave); zCoords[2] = zCoords[2] - this->CornerOffset * (zCoords[2] - ave); ave = (zCoords[1] + zCoords[3]) / 2.0; zCoords[1] = zCoords[1] - this->CornerOffset * (zCoords[1] - ave); zCoords[3] = zCoords[3] - this->CornerOffset * (zCoords[3] - ave); ave = (zRange[1] + zRange[0]) / 2.0; if (!this->ShowActualBounds) { zRange[0] = zRange[0] - this->CornerOffset * (zRange[0] - ave); zRange[1] = zRange[1] - this->CornerOffset * (zRange[1] - ave); } } } //---------------------------------------------------------------------------- // Release any graphics resources that are being consumed by this actor. // The parameter window could be used to determine which graphic // resources to release. void vtkCubeAxesActor2D::ReleaseGraphicsResources(vtkWindow *win) { this->XAxis->ReleaseGraphicsResources(win); this->YAxis->ReleaseGraphicsResources(win); this->ZAxis->ReleaseGraphicsResources(win); } //---------------------------------------------------------------------------- // Return the ranges void vtkCubeAxesActor2D::GetRanges(double ranges[6]) { int i; for ( i=0; i<6; i++ ) { ranges[i] = this->Ranges[i]; } } //---------------------------------------------------------------------------- // Compute the ranges void vtkCubeAxesActor2D::GetRanges(double& xmin, double& xmax, double& ymin, double& ymax, double& zmin, double& zmax) { double ranges[6]; this->GetRanges(ranges); xmin = ranges[0]; xmax = ranges[1]; ymin = ranges[2]; ymax = ranges[3]; zmin = ranges[4]; zmax = ranges[5]; } //---------------------------------------------------------------------------- // Compute the bounds double *vtkCubeAxesActor2D::GetRanges() { double ranges[6]; this->GetRanges(ranges); return this->Ranges; } //---------------------------------------------------------------------------- // Compute the bounds void vtkCubeAxesActor2D::GetBounds(double bounds[6]) { double *propBounds; int i; if ( this->Input ) { this->Input->Update(); this->Input->GetBounds(bounds); for (i=0; i< 6; i++) { this->Bounds[i] = bounds[i]; } } else if ( this->ViewProp && ((propBounds = this->ViewProp->GetBounds()) && propBounds != NULL) ) { for (i=0; i< 6; i++) { bounds[i] = this->Bounds[i] = propBounds[i]; } } else { for (i=0; i< 6; i++) { bounds[i] = this->Bounds[i]; } } } //---------------------------------------------------------------------------- // Compute the bounds void vtkCubeAxesActor2D::GetBounds(double& xmin, double& xmax, double& ymin, double& ymax, double& zmin, double& zmax) { double bounds[6]; this->GetBounds(bounds); xmin = bounds[0]; xmax = bounds[1]; ymin = bounds[2]; ymax = bounds[3]; zmin = bounds[4]; zmax = bounds[5]; } //---------------------------------------------------------------------------- // Compute the bounds double *vtkCubeAxesActor2D::GetBounds() { this->GetBounds(this->Bounds); return this->Bounds; } //---------------------------------------------------------------------------- void vtkCubeAxesActor2D::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); if ( this->Input ) { os << indent << "Input: (" << (void *)this->Input << ")\n"; } else { os << indent << "Input: (none)\n"; } if ( this->ViewProp ) { os << indent << "ViewProp: (" << (void *)this->ViewProp << ")\n"; } else { os << indent << "ViewProp: (none)\n"; } os << indent << "Bounds: \n"; os << indent << " Xmin,Xmax: (" << this->Bounds[0] << ", " << this->Bounds[1] << ")\n"; os << indent << " Ymin,Ymax: (" << this->Bounds[2] << ", " << this->Bounds[3] << ")\n"; os << indent << " Zmin,Zmax: (" << this->Bounds[4] << ", " << this->Bounds[5] << ")\n"; if ( this->Camera ) { os << indent << "Camera:\n"; this->Camera->PrintSelf(os,indent.GetNextIndent()); } else { os << indent << "Camera: (none)\n"; } if (this->AxisTitleTextProperty) { os << indent << "Axis Title Text Property:\n"; this->AxisTitleTextProperty->PrintSelf(os,indent.GetNextIndent()); } else { os << indent << "Axis Title Text Property: (none)\n"; } if (this->AxisLabelTextProperty) { os << indent << "Axis Label Text Property:\n"; this->AxisLabelTextProperty->PrintSelf(os,indent.GetNextIndent()); } else { os << indent << "Axis Label Text Property: (none)\n"; } if ( this->FlyMode == VTK_FLY_CLOSEST_TRIAD ) { os << indent << "Fly Mode: CLOSEST_TRIAD\n"; } else { os << indent << "Fly Mode: OUTER_EDGES\n"; } os << indent << "Scaling: " << (this->Scaling ? "On\n" : "Off\n"); os << indent << "UseRanges: " << (this->UseRanges ? "On\n" : "Off\n"); os << indent << "Ranges: \n"; os << indent << " Xmin,Xmax: (" << this->Ranges[0] << ", " << this->Ranges[1] << ")\n"; os << indent << " Ymin,Ymax: (" << this->Ranges[2] << ", " << this->Ranges[3] << ")\n"; os << indent << " Zmin,Zmax: (" << this->Ranges[4] << ", " << this->Ranges[5] << ")\n"; os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n"; os << indent << "X Label: " << this->XLabel << "\n"; os << indent << "Y Label: " << this->YLabel << "\n"; os << indent << "Z Label: " << this->ZLabel << "\n"; os << indent << "X Axis Visibility: " << (this->XAxisVisibility ? "On\n" : "Off\n"); os << indent << "Y Axis Visibility: " << (this->YAxisVisibility ? "On\n" : "Off\n"); os << indent << "Z Axis Visibility: " << (this->ZAxisVisibility ? "On\n" : "Off\n"); os << indent << "Label Format: " << this->LabelFormat << "\n"; os << indent << "Font Factor: " << this->FontFactor << "\n"; os << indent << "Inertia: " << this->Inertia << "\n"; os << indent << "Corner Offset: " << this->CornerOffset << "\n"; os << indent << "UseRanges: " << (this->UseRanges ? "On" : "Off") << "\n"; os << indent << "Ranges: " << this->Ranges[0] << ", " << this->Ranges[1] << ", " << this->Ranges[2] << ", " << this->Ranges[3] << ", " << this->Ranges[4] << ", " << this->Ranges[5] << "\n"; os << indent << "Show Actual Bounds: " << (this->ShowActualBounds ? "On\n" : "Off\n"); } //---------------------------------------------------------------------------- static int IsInBounds(double x[3], double bounds[6]); // Clip the axes to fit into the viewport. Do this clipping each of the three // axes to determine which part of the cube is in view. Returns 0 if // nothing should be drawn. #define VTK_DIVS 10 int vtkCubeAxesActor2D::ClipBounds(vtkViewport *viewport, double pts[8][3], double bounds[6]) { int i, j, k, numIters; double planes[24]; double x[3]; double val, maxVal=0, anchor[3], scale; double delX, delY, delZ; double bounds2[6]; double scale2, newScale, origin[3]; double aspect[2]; // Only do this mojo if scaling is required if ( ! this->Scaling ) { return 1; } // Get the 6 planes defining the view frustrum viewport->GetAspect( aspect ); this->Camera->GetFrustumPlanes((aspect[0] / aspect[1]), planes); // Hunt for the point in the bounds furthest inside the frustum // Iteratively loop over points in bounding box and evaluate the // maximum minimum distance. Find the point furthest inside of the // bounding box. Use this as an anchor point to scale to. Repeat // the process to hone in on the best point. delX = (bounds[1]-bounds[0]) / (VTK_DIVS-1); delY = (bounds[3]-bounds[2]) / (VTK_DIVS-1); delZ = (bounds[5]-bounds[4]) / (VTK_DIVS-1); anchor[0] = (bounds[1]+bounds[0])/2.0; anchor[1] = (bounds[3]+bounds[2])/2.0; anchor[2] = (bounds[5]+bounds[4])/2.0; for ( numIters=0; numIters < 8; numIters++) { origin[0] = anchor[0] - delX*(VTK_DIVS-1)/2.0; origin[1] = anchor[1] - delY*(VTK_DIVS-1)/2.0; origin[2] = anchor[2] - delZ*(VTK_DIVS-1)/2.0; for (maxVal=0.0, k=0; kEvaluatePoint(planes, x); if ( val > maxVal ) { anchor[0] = x[0]; anchor[1] = x[1]; anchor[2] = x[2]; maxVal = val; } }//if in bounding box }//i }//j }//k delX /= (VTK_DIVS-1) * 1.414; delY /= (VTK_DIVS-1) * 1.414; delZ /= (VTK_DIVS-1) * 1.414; }//Iteratively find anchor point if ( maxVal <= 0.0 ) { return 0; //couldn't find a point inside } // Now iteratively scale the bounding box until all points are inside // the frustrum. Use bisection method. scale = 1.0; scale2 = 0.00001; val = this->EvaluateBounds(planes, bounds); // Get other end point for bisection technique for (i=0; i<3; i++) { bounds2[2*i] = (bounds[2*i]-anchor[i])*scale2 + anchor[i]; bounds2[2*i+1] = (bounds[2*i+1]-anchor[i])*scale2 + anchor[i]; } val = this->EvaluateBounds(planes, bounds2); if ( val <= 0.0 ) { return 0; //not worth drawing - too small } for ( numIters=0; numIters < 10; numIters++) { newScale = (scale + scale2) / 2.0; for (i=0; i<3; i++) { bounds2[2*i] = (bounds[2*i]-anchor[i])*newScale + anchor[i]; bounds2[2*i+1] = (bounds[2*i+1]-anchor[i])*newScale + anchor[i]; } val = this->EvaluateBounds(planes, bounds2); if ( val > 0.0 ) { scale2 = newScale; } else { scale = newScale; } }//for converged for (i=0; i<6; i++) //copy the result { bounds[i] = bounds2[i]; } this->TransformBounds(viewport, bounds, pts); return 1; } #undef VTK_DIVS //---------------------------------------------------------------------------- void vtkCubeAxesActor2D::TransformBounds(vtkViewport *viewport, double bounds[6], double pts[8][3]) { int i, j, k, idx; double x[3]; //loop over verts of bounding box for (k=0; k<2; k++) { x[2] = bounds[4+k]; for (j=0; j<2; j++) { x[1] = bounds[2+j]; for (i=0; i<2; i++) { idx = i + 2*j + 4*k; x[0] = bounds[i]; viewport->SetWorldPoint(x[0],x[1],x[2],1.0); viewport->WorldToDisplay(); viewport->GetDisplayPoint(pts[idx]); } } } } //---------------------------------------------------------------------------- // Return smallest value of point evaluated against frustum planes. Also // sets the closest point coordinates in xyz. double vtkCubeAxesActor2D::EvaluatePoint(double planes[24], double x[3]) { int kk; double *plane; double val, minPlanesValue; for (minPlanesValue=VTK_DOUBLE_MAX, kk=0; kk<6 ; kk++) { plane = planes + kk*4; val = plane[0]*x[0] + plane[1]*x[1] + plane[2]*x[2] + plane[3]; if ( val < minPlanesValue ) { minPlanesValue = val; } }//for all planes return minPlanesValue; } //---------------------------------------------------------------------------- // Return the smallest point of the bounding box evaluated against the // frustum planes. double vtkCubeAxesActor2D::EvaluateBounds(double planes[24], double bounds[6]) { double val, minVal, x[3]; int i, j, k; for (minVal=VTK_DOUBLE_MAX, k=0; k<2; k++) { x[2] = bounds[4+k]; for (j=0; j<2; j++) { x[1] = bounds[2+j]; for (i=0; i<2; i++) { x[0] = bounds[i]; val = this->EvaluatePoint(planes, x); if ( val < minVal ) { minVal = val; } } } }//loop over verts of bounding box return minVal; } //---------------------------------------------------------------------------- static int IsInBounds(double x[3], double bounds[6]) { if ( x[0] < bounds[0] || x[0] > bounds[1] || x[1] < bounds[2] || x[1] > bounds[3] || x[2] < bounds[4] || x[2] > bounds[5]) { return 0; } else { return 1; } } //---------------------------------------------------------------------------- // Disable warnings about qualifiers on return types. #if defined(_COMPILER_VERSION) # pragma set woff 3303 #endif #if defined(__INTEL_COMPILER) # pragma warning (disable:858) #endif #ifndef VTK_LEGACY_REMOVE # ifdef VTK_WORKAROUND_WINDOWS_MANGLE # undef SetProp # undef GetProp void const vtkCubeAxesActor2D::SetPropA(vtkProp* prop) { VTK_LEGACY_REPLACED_BODY(vtkCubeAxesActor2D::SetProp, "VTK 5.0", vtkCubeAxesActor2D::SetViewProp); this->SetViewProp(prop); } void const vtkCubeAxesActor2D::SetPropW(vtkProp* prop) { VTK_LEGACY_REPLACED_BODY(vtkCubeAxesActor2D::SetProp, "VTK 5.0", vtkCubeAxesActor2D::SetViewProp); this->SetViewProp(prop); } vtkProp* const vtkCubeAxesActor2D::GetPropA() { VTK_LEGACY_REPLACED_BODY(vtkCubeAxesActor2D::GetProp, "VTK 5.0", vtkCubeAxesActor2D::GetViewProp); return this->GetViewProp(); } vtkProp* const vtkCubeAxesActor2D::GetPropW() { VTK_LEGACY_REPLACED_BODY(vtkCubeAxesActor2D::GetProp, "VTK 5.0", vtkCubeAxesActor2D::GetViewProp); return this->GetViewProp(); } # endif void const vtkCubeAxesActor2D::SetProp(vtkProp* prop) { VTK_LEGACY_REPLACED_BODY(vtkCubeAxesActor2D::SetProp, "VTK 5.0", vtkCubeAxesActor2D::SetViewProp); this->SetViewProp(prop); } vtkProp* const vtkCubeAxesActor2D::GetProp() { VTK_LEGACY_REPLACED_BODY(vtkCubeAxesActor2D::GetProp, "VTK 5.0", vtkCubeAxesActor2D::GetViewProp); return this->GetViewProp(); } #endif