#include <G4VisCommandsSceneAdd.hh>
Inheritance diagram for G4VisCommandSceneAddScale:
Public Member Functions | |
G4VisCommandSceneAddScale () | |
virtual | ~G4VisCommandSceneAddScale () |
G4String | GetCurrentValue (G4UIcommand *command) |
void | SetNewValue (G4UIcommand *command, G4String newValue) |
Definition at line 312 of file G4VisCommandsSceneAdd.hh.
G4VisCommandSceneAddScale::G4VisCommandSceneAddScale | ( | ) |
Definition at line 1711 of file G4VisCommandsSceneAdd.cc.
References G4Scale::GetGuidanceString(), G4UIparameter::SetDefaultValue(), G4UIparameter::SetGuidance(), and G4UIcommand::SetParameter().
01711 { 01712 G4bool omitable; 01713 fpCommand = new G4UIcommand ("/vis/scene/add/scale", this); 01714 fpCommand -> SetGuidance 01715 ("Adds an annotated scale line to the current scene."); 01716 fpCommand -> SetGuidance (G4Scale::GetGuidanceString()); 01717 G4UIparameter* parameter; 01718 parameter = new G4UIparameter ("length", 'd', omitable = true); 01719 parameter->SetDefaultValue (1.); 01720 fpCommand->SetParameter (parameter); 01721 parameter = new G4UIparameter ("unit", 's', omitable = true); 01722 parameter->SetGuidance 01723 ("auto or valid length unit - defaults to auto." 01724 "\nIf auto, length is roughly one tenth of the scene extent."); 01725 parameter->SetDefaultValue ("auto"); 01726 fpCommand->SetParameter (parameter); 01727 parameter = new G4UIparameter ("direction", 's', omitable = true); 01728 parameter->SetGuidance 01729 ("auto|x|y|z - defaults to auto." 01730 "\nIf auto, scale is roughly in the plane of the current view."); 01731 parameter->SetDefaultValue ("auto"); 01732 fpCommand->SetParameter (parameter); 01733 parameter = new G4UIparameter ("red", 'd', omitable = true); 01734 parameter->SetDefaultValue (1.); 01735 fpCommand->SetParameter (parameter); 01736 parameter = new G4UIparameter ("green", 'd', omitable = true); 01737 parameter->SetDefaultValue (0.); 01738 fpCommand->SetParameter (parameter); 01739 parameter = new G4UIparameter ("blue", 'd', omitable = true); 01740 parameter->SetDefaultValue (0.); 01741 fpCommand->SetParameter (parameter); 01742 parameter = new G4UIparameter ("auto|manual", 's', omitable = true); 01743 parameter->SetGuidance 01744 ("Automatic placement or manual placement at (xmid,ymid,zmid)." 01745 "\nIf automatic, scale is placed at bottom left of current view."); 01746 parameter -> SetParameterCandidates("auto manual"); 01747 parameter->SetDefaultValue ("auto"); 01748 fpCommand->SetParameter (parameter); 01749 parameter = new G4UIparameter ("xmid", 'd', omitable = true); 01750 parameter->SetDefaultValue (0.); 01751 fpCommand->SetParameter (parameter); 01752 parameter = new G4UIparameter ("ymid", 'd', omitable = true); 01753 parameter->SetDefaultValue (0.); 01754 fpCommand->SetParameter (parameter); 01755 parameter = new G4UIparameter ("zmid", 'd', omitable = true); 01756 parameter->SetDefaultValue (0.); 01757 fpCommand->SetParameter (parameter); 01758 parameter = new G4UIparameter ("unit", 's', omitable = true); 01759 parameter->SetDefaultValue ("m"); 01760 fpCommand->SetParameter (parameter); 01761 }
G4VisCommandSceneAddScale::~G4VisCommandSceneAddScale | ( | ) | [virtual] |
G4String G4VisCommandSceneAddScale::GetCurrentValue | ( | G4UIcommand * | command | ) | [virtual] |
void G4VisCommandSceneAddScale::SetNewValue | ( | G4UIcommand * | command, | |
G4String | newValue | |||
) | [virtual] |
Reimplemented from G4UImessenger.
Definition at line 1771 of file G4VisCommandsSceneAdd.cc.
References G4VisManager::confirmations, G4VisManager::errors, G4VVisCommand::fpVisManager, G4BestUnit, G4cout, G4endl, G4VisManager::GetCurrentScene(), G4VisManager::GetCurrentViewer(), G4Scene::GetExtent(), G4VisExtent::GetExtentRadius(), G4ViewParameters::GetUpVector(), G4VisManager::GetVerbosity(), G4VViewer::GetViewParameters(), G4ViewParameters::GetViewpointDirection(), G4VisExtent::GetXmax(), G4VisExtent::GetXmin(), G4VisExtent::GetYmax(), G4VisExtent::GetYmin(), G4VisExtent::GetZmax(), G4VisExtent::GetZmin(), G4VisManager::parameters, G4VModel::SetExtent(), G4VModel::SetTransformation(), G4Visible::SetVisAttributes(), G4VVisCommand::UpdateVisManagerScene(), G4UIcommand::ValueOf(), G4VisManager::warnings, G4Scale::x, G4Scale::y, and G4Scale::z.
01771 { 01772 01773 G4VisManager::Verbosity verbosity = fpVisManager->GetVerbosity(); 01774 G4bool warn = verbosity >= G4VisManager::warnings; 01775 01776 G4Scene* pScene = fpVisManager->GetCurrentScene(); 01777 if (!pScene) { 01778 if (verbosity >= G4VisManager::errors) { 01779 G4cout << "ERROR: No current scene. Please create one." << G4endl; 01780 } 01781 return; 01782 } 01783 01784 G4double userLength, red, green, blue, xmid, ymid, zmid; 01785 G4String userLengthUnit, direction, auto_manual, positionUnit; 01786 std::istringstream is (newValue); 01787 is >> userLength >> userLengthUnit >> direction 01788 >> red >> green >> blue 01789 >> auto_manual 01790 >> xmid >> ymid >> zmid >> positionUnit; 01791 01792 G4double length = userLength; 01793 const G4VisExtent& sceneExtent = pScene->GetExtent(); // Existing extent. 01794 if (userLengthUnit == "auto") { 01795 length *= sceneExtent.GetExtentRadius(); 01796 G4double intLog10Length = std::floor(std::log10(length)); 01797 length = std::pow(10,intLog10Length); 01798 } else { 01799 length *= G4UIcommand::ValueOf(userLengthUnit); 01800 } 01801 G4String annotation = G4BestUnit(length,"Length"); 01802 01803 G4double unit = G4UIcommand::ValueOf(positionUnit); 01804 xmid *= unit; ymid *= unit; zmid *= unit; 01805 01806 G4Scale::Direction scaleDirection (G4Scale::x); 01807 if (direction(0) == 'y') scaleDirection = G4Scale::y; 01808 if (direction(0) == 'z') scaleDirection = G4Scale::z; 01809 01810 G4VViewer* pViewer = fpVisManager->GetCurrentViewer(); 01811 if (!pViewer) { 01812 if (verbosity >= G4VisManager::errors) { 01813 G4cout << 01814 "ERROR: G4VisCommandSceneAddScale::SetNewValue: no viewer." 01815 "\n Auto direction needs a viewer." 01816 << G4endl; 01817 } 01818 return; 01819 } 01820 01821 const G4Vector3D& vp = 01822 pViewer->GetViewParameters().GetViewpointDirection(); 01823 const G4Vector3D& up = 01824 pViewer->GetViewParameters().GetUpVector(); 01825 01826 if (direction == "auto") { // Takes cue from viewer. 01827 if (std::abs(vp.x()) > std::abs(vp.y()) && 01828 std::abs(vp.x()) > std::abs(vp.z())) { // x viewpoint 01829 if (std::abs(up.y()) > std::abs(up.z())) scaleDirection = G4Scale::z; 01830 else scaleDirection = G4Scale::y; 01831 } 01832 else if (std::abs(vp.y()) > std::abs(vp.x()) && 01833 std::abs(vp.y()) > std::abs(vp.z())) { // y viewpoint 01834 if (std::abs(up.x()) > std::abs(up.z())) scaleDirection = G4Scale::z; 01835 else scaleDirection = G4Scale::x; 01836 } 01837 else if (std::abs(vp.z()) > std::abs(vp.x()) && 01838 std::abs(vp.z()) > std::abs(vp.y())) { // z viewpoint 01839 if (std::abs(up.y()) > std::abs(up.x())) scaleDirection = G4Scale::x; 01840 else scaleDirection = G4Scale::y; 01841 } 01842 } 01843 01844 G4bool autoPlacing = false; if (auto_manual == "auto") autoPlacing = true; 01845 // Parameters read and interpreted. 01846 01847 // Useful constants, etc... 01848 const G4double halfLength(length / 2.); 01849 const G4double comfort(0.01); // 0.15 seems too big. 0.05 might be better. 01850 const G4double freeLengthFraction (1. + 2. * comfort); 01851 01852 const G4double xmin = sceneExtent.GetXmin(); 01853 const G4double xmax = sceneExtent.GetXmax(); 01854 const G4double ymin = sceneExtent.GetYmin(); 01855 const G4double ymax = sceneExtent.GetYmax(); 01856 const G4double zmin = sceneExtent.GetZmin(); 01857 const G4double zmax = sceneExtent.GetZmax(); 01858 01859 // Test existing extent and issue warnings... 01860 G4bool worried = false; 01861 if (sceneExtent.GetExtentRadius() == 0) { 01862 worried = true; 01863 if (verbosity >= G4VisManager::warnings) { 01864 G4cout << 01865 "WARNING: Existing scene does not yet have any extent." 01866 "\n Maybe you have not yet added any geometrical object." 01867 << G4endl; 01868 } 01869 } 01870 // Test existing scene for room... 01871 G4bool room = true; 01872 switch (scaleDirection) { 01873 case G4Scale::x: 01874 if (freeLengthFraction * (xmax - xmin) < length) room = false; break; 01875 case G4Scale::y: 01876 if (freeLengthFraction * (ymax - ymin) < length) room = false; break; 01877 case G4Scale::z: 01878 if (freeLengthFraction * (zmax - zmin) < length) room = false; break; 01879 } 01880 if (!room) { 01881 worried = true; 01882 if (verbosity >= G4VisManager::warnings) { 01883 G4cout << 01884 "WARNING: Not enough room in existing scene. Maybe scale is too long." 01885 << G4endl; 01886 } 01887 } 01888 if (worried) { 01889 if (verbosity >= G4VisManager::warnings) { 01890 G4cout << 01891 "WARNING: The scale you have asked for is bigger than the existing" 01892 "\n scene. Maybe you have added it too soon. It is recommended that" 01893 "\n you add the scale last so that it can be correctly auto-positioned" 01894 "\n so as not to be obscured by any existing object and so that the" 01895 "\n view parameters can be correctly recalculated." 01896 << G4endl; 01897 } 01898 } 01899 01900 // Let's go ahead a construct a scale and a scale model. Since the 01901 // placing is done here, this G4Scale is *not* auto-placed... 01902 G4Scale scale(length, annotation, scaleDirection, 01903 false, xmid, ymid, zmid); 01904 G4VisAttributes* pVisAttr = new G4VisAttributes(G4Colour(red, green, blue)); 01905 // Created of the heap because it needs a long lifetime. This is a 01906 // mess. The model determines the life but the vis atttributes are 01907 // associated with the scale. There's no way of knowing when to 01908 // delete the vis atttributes!!! 01909 scale.SetVisAttributes(pVisAttr); 01910 G4VModel* model = new G4ScaleModel(scale); 01911 01912 // Now figure out the extent... 01913 // 01914 // From the G4Scale.hh: 01915 // 01916 // This creates a representation of annotated line in the specified 01917 // direction with tick marks at the end. If autoPlacing is true it 01918 // is required to be centred at the front, right, bottom corner of 01919 // the world space, comfortably outside the existing bounding 01920 // box/sphere so that existing objects do not obscure it. Otherwise 01921 // it is required to be drawn with mid-point at (xmid, ymid, zmid). 01922 // 01923 // The auto placing algorithm might be: 01924 // x = xmin + (1 + comfort) * (xmax - xmin) 01925 // y = ymin - comfort * (ymax - ymin) 01926 // z = zmin + (1 + comfort) * (zmax - zmin) 01927 // if direction == x then (x - length,y,z) to (x,y,z) 01928 // if direction == y then (x,y,z) to (x,y + length,z) 01929 // if direction == z then (x,y,z - length) to (x,y,z) 01930 // 01931 // End of clip from G4Scale.hh: 01932 // 01933 // Implement this in two parts. Here, use the scale's extent to 01934 // "expand" the scene's extent. Then rendering - in 01935 // G4VSceneHandler::AddPrimitive(const G4Scale&) - simply has to 01936 // ensure it's within the new extent. 01937 // 01938 01939 G4double sxmid(xmid), symid(ymid), szmid(zmid); 01940 if (autoPlacing) { 01941 // Aim to place at bottom right of screen in current view. 01942 // Give some comfort zone. 01943 const G4double xComfort = comfort * (xmax - xmin); 01944 const G4double yComfort = comfort * (ymax - ymin); 01945 const G4double zComfort = comfort * (zmax - zmin); 01946 switch (scaleDirection) { 01947 case G4Scale::x: 01948 if (vp.z() > 0.) { 01949 sxmid = xmax + xComfort; 01950 symid = ymin - yComfort; 01951 szmid = zmin - zComfort; 01952 } else { 01953 sxmid = xmin - xComfort; 01954 symid = ymin - yComfort; 01955 szmid = zmax + zComfort; 01956 } 01957 break; 01958 case G4Scale::y: 01959 if (vp.x() > 0.) { 01960 sxmid = xmin - xComfort; 01961 symid = ymax + yComfort; 01962 szmid = zmin - zComfort; 01963 } else { 01964 sxmid = xmax + xComfort; 01965 symid = ymin - yComfort; 01966 szmid = zmin - zComfort; 01967 } 01968 break; 01969 case G4Scale::z: 01970 if (vp.x() > 0.) { 01971 sxmid = xmax + xComfort; 01972 symid = ymin - yComfort; 01973 szmid = zmax + zComfort; 01974 } else { 01975 sxmid = xmin - xComfort; 01976 symid = ymin - yComfort; 01977 szmid = zmax + zComfort; 01978 } 01979 break; 01980 } 01981 } 01982 01983 /* Old code - kept for future reference. 01984 G4double sxmid(xmid), symid(ymid), szmid(zmid); 01985 if (autoPlacing) { 01986 sxmid = xmin + onePlusComfort * (xmax - xmin); 01987 symid = ymin - comfort * (ymax - ymin); 01988 szmid = zmin + onePlusComfort * (zmax - zmin); 01989 switch (scaleDirection) { 01990 case G4Scale::x: 01991 sxmid -= halfLength; 01992 break; 01993 case G4Scale::y: 01994 symid += halfLength; 01995 break; 01996 case G4Scale::z: 01997 szmid -= halfLength; 01998 break; 01999 } 02000 } 02001 */ 02002 02003 /* sxmin, etc., not actually used. Comment out to prevent compiler 02004 warnings but keep in case need in future. Extract transform and 02005 scaleExtent into reduced code below. 02006 G4double sxmin(sxmid), sxmax(sxmid); 02007 G4double symin(symid), symax(symid); 02008 G4double szmin(szmid), szmax(szmid); 02009 G4Transform3D transform; 02010 G4VisExtent scaleExtent; 02011 switch (scaleDirection) { 02012 case G4Scale::x: 02013 sxmin = sxmid - halfLength; 02014 sxmax = sxmid + halfLength; 02015 scaleExtent = G4VisExtent(-halfLength,halfLength,0,0,0,0); 02016 break; 02017 case G4Scale::y: 02018 symin = symid - halfLength; 02019 symax = symid + halfLength; 02020 transform = G4RotateZ3D(halfpi); 02021 scaleExtent = G4VisExtent(0,0,-halfLength,halfLength,0,0); 02022 break; 02023 case G4Scale::z: 02024 szmin = szmid - halfLength; 02025 szmax = szmid + halfLength; 02026 transform = G4RotateY3D(halfpi); 02027 scaleExtent = G4VisExtent(0,0,0,0,-halfLength,halfLength); 02028 break; 02029 } 02030 */ 02031 G4Transform3D transform; 02032 G4VisExtent scaleExtent; 02033 switch (scaleDirection) { 02034 case G4Scale::x: 02035 scaleExtent = G4VisExtent(-halfLength,halfLength,0,0,0,0); 02036 break; 02037 case G4Scale::y: 02038 transform = G4RotateZ3D(halfpi); 02039 scaleExtent = G4VisExtent(0,0,-halfLength,halfLength,0,0); 02040 break; 02041 case G4Scale::z: 02042 transform = G4RotateY3D(halfpi); 02043 scaleExtent = G4VisExtent(0,0,0,0,-halfLength,halfLength); 02044 break; 02045 } 02046 transform = G4Translate3D(sxmid,symid,szmid) * transform; 02048 02049 02050 model->SetTransformation(transform); 02051 // Note: it is the responsibility of the model to act upon this, but 02052 // the extent is in local coordinates... 02053 model->SetExtent(scaleExtent); 02054 // This extent gets "added" to existing scene extent in 02055 // AddRunDurationModel below. 02056 02057 const G4String& currentSceneName = pScene -> GetName (); 02058 G4bool successful = pScene -> AddRunDurationModel (model, warn); 02059 if (successful) { 02060 if (verbosity >= G4VisManager::confirmations) { 02061 G4cout << "Scale of " << annotation 02062 << " added to scene \"" << currentSceneName << "\"."; 02063 if (verbosity >= G4VisManager::parameters) { 02064 G4cout << "\n with extent " << scaleExtent 02065 << "\n at " << transform.getRotation() 02066 << transform.getTranslation(); 02067 } 02068 G4cout << G4endl; 02069 } 02070 } 02071 else G4VisCommandsSceneAddUnsuccessful(verbosity); 02072 UpdateVisManagerScene (currentSceneName); 02073 }