diff --git a/OpenRoadEd/CMakeLists.txt b/OpenRoadEd/CMakeLists.txt index af2bafa1fd616bc5a327dfa0894eb1abac51d8af..0a5509bd1998beda35012fd6a89fdfc4bb9c3c80 100644 --- a/OpenRoadEd/CMakeLists.txt +++ b/OpenRoadEd/CMakeLists.txt @@ -62,6 +62,7 @@ set(TARGET_H "${CMAKE_SOURCE_DIR}/OpenDrive/OpenDriveXmlParser.h" "${CMAKE_SOURCE_DIR}/Qt/SettingsWidgets/SettingsLane.h" "${CMAKE_SOURCE_DIR}/Qt/SettingsWidgets/SettingsRoad.h" "${CMAKE_SOURCE_DIR}/Qt/SettingsWidgets/SettingsRoadSignal.h" + "${CMAKE_SOURCE_DIR}/Qt/SettingsWidgets/SettingsRoadObject.h" "${CMAKE_SOURCE_DIR}/Qt/SettingsWidgets/SettingsLaneWidthRecord.h" "${CMAKE_SOURCE_DIR}/Qt/SettingsWidgets/SettingsLateralProfileCrossfall.h" "${CMAKE_SOURCE_DIR}/Qt/ToolsDialogs/GetRoadDialog.h" @@ -101,6 +102,7 @@ set(TARGET_CPP "${CMAKE_SOURCE_DIR}/OpenDrive/OpenDriveXmlWriter.cpp" "${CMAKE_SOURCE_DIR}/Qt/QOSGWidget.cpp" "${CMAKE_SOURCE_DIR}/Qt/SettingsWidgets/SettingsRoad.cpp" "${CMAKE_SOURCE_DIR}/Qt/SettingsWidgets/SettingsRoadSignal.cpp" + "${CMAKE_SOURCE_DIR}/Qt/SettingsWidgets/SettingsRoadObject.cpp" "${CMAKE_SOURCE_DIR}/Qt/SettingsWidgets/SettingsPage.cpp" "${CMAKE_SOURCE_DIR}/Qt/SettingsWidgets/SettingsLateralProfileSuper.cpp" "${CMAKE_SOURCE_DIR}/Qt/SettingsWidgets/SettingsElevationRecord.cpp" diff --git a/OpenRoadEd/OpenDrive/ObjectSignal.cpp b/OpenRoadEd/OpenDrive/ObjectSignal.cpp index bc0f6c6ea003c54b1fd11c47624012b437e7be93..9b7ef8fac7f0c45d009a0790b83e7a798fa7f30d 100644 --- a/OpenRoadEd/OpenDrive/ObjectSignal.cpp +++ b/OpenRoadEd/OpenDrive/ObjectSignal.cpp @@ -1,4 +1,286 @@ #include "ObjectSignal.h" +#include <iostream> + +Object::Object() +{ + mS=0.0; + mT=0.0; + mId="-1"; + mName=""; + mDynamic=false; + mOrientation="none"; + mZOffset=0.0; + mValidLength=0.0; + mType="-1"; + mSubType="-1"; + mHeading=0.0; + mPitch=0.0; + mRoll=0.0; + mBoundingBox=false; + mBoundingCylinder=false; +} + +Object::Object(std::string &name,std::string &id) +{ + mS=0.0; + mT=0.0; + mId=id; + mName=name; + mDynamic=false; + mOrientation="none"; + mZOffset=0.0; + mValidLength=0.0; + mType="-1"; + mSubType="-1"; + mHeading=0.0; + mPitch=0.0; + mRoll=0.0; + mBoundingBox=false; + mBoundingCylinder=false; +} + +Object::Object(const Object &object) +{ + mS=object.mS; + mT=object.mT; + mId=object.mId; + mName=object.mName; + mDynamic=object.mDynamic; + mOrientation=object.mOrientation; + mZOffset=object.mZOffset; + mValidLength=object.mValidLength; + mType=object.mType; + mSubType=object.mSubType; + mHeading=object.mHeading; + mPitch=object.mPitch; + mRoll=object.mRoll; + mBoundingBox=object.mBoundingBox; + if(mBoundingBox) + { + mBounding.box.length=object.mBounding.box.length; + mBounding.box.width=object.mBounding.box.width; + mBounding.box.height=object.mBounding.box.height; + } + mBoundingCylinder=object.mBoundingCylinder; + if(mBoundingCylinder) + { + mBounding.cylinder.radius=object.mBounding.cylinder.radius; + mBounding.cylinder.height=object.mBounding.cylinder.height; + } +} + +const Object &Object::operator=(const Object &rhs) +{ + std::cout << "= operator" << std::endl; +} + + +double Object::GetS(void) +{ + return mS; +} + +double Object::GetT(void) +{ + return mT; +} + +std::string Object::GetId(void) +{ + return mId; +} + +std::string Object::GetName(void) +{ + return mName; +} + +bool Object::IsDynamic(void) +{ + return mDynamic; +} + +std::string Object::GetOrientation(void) +{ + return mOrientation; +} + +double Object::GetZOffset(void) +{ + return mZOffset; +} + +double Object::GetValidLength(void) +{ + return mValidLength; +} + +std::string Object::GetType(void) +{ + return mType; +} + +std::string Object::GetSubType(void) +{ + return mSubType; +} + +double Object::GetHeading(void) +{ + return mHeading; +} + +double Object::GetPitch(void) +{ + return mPitch; +} + +double Object::GetRoll(void) +{ + return mRoll; +} + +bool Object::IsBoundigBox(void) +{ + return mBoundingBox; +} + +TBoundingBox Object::GetBoundingBox(void) +{ + return mBounding.box; +} + +bool Object::GetBoundingBox(double &length,double &width,double &height) +{ + if(mBoundingBox) + { + length=mBounding.box.length; + width=mBounding.box.width; + height=mBounding.box.height; + } + else + { + length=0.0; + width=0.0; + height=0.0; + } + + return mBoundingBox; +} + +bool Object::IsBoundigCylinder(void) +{ + return mBoundingCylinder; +} + +TBoundingCylinder Object::GetBoundingCylinder(void) +{ + return mBounding.cylinder; +} + +bool Object::GetBoundingCylinder(double &radius,double &height) +{ + if(mBoundingCylinder) + { + radius=mBounding.cylinder.radius; + height=mBounding.cylinder.height; + } + else + { + radius=0.0; + height=0.0; + } + + return mBoundingCylinder; +} + +void Object::SetS(const double s) +{ + mS=s; +} + +void Object::SetT(const double t) +{ + mT=t; +} + +void Object::SetId(const std::string &id) +{ + mId=id; +} + +void Object::SetName(const std::string &name) +{ + mName=name; +} + +void Object::SetDynamic(const bool dynamic) +{ + mDynamic=dynamic; +} + +void Object::SetOrientation(const std::string &orientation) +{ + mOrientation=orientation; +} + +void Object::SetZOffset(const double zOffset) +{ + mZOffset=zOffset; +} + +void Object::SetValidLength(const double length) +{ + mValidLength=length; +} + +void Object::SetType(const std::string &type) +{ + mType=type; +} + +void Object::SetSubType(const std::string &subType) +{ + mSubType=subType; +} + +void Object::SetHeading(const double heading) +{ + mHeading=heading; +} + +void Object::SetPitch(const double pitch) +{ + mPitch=pitch; +} + +void Object::SetRoll(const double roll) +{ + mRoll=roll; +} + +void Object::SetBoundingBox(double length,double width,double height) +{ + mBounding.box.length=length; + mBounding.box.width=width; + mBounding.box.height=height; + mBoundingBox=true; + mBoundingCylinder=false; +} + +void Object::SetBoundingCylinder(double radius,double height) +{ + mBounding.cylinder.radius=radius; + mBounding.cylinder.height=height; + mBoundingBox=false; + mBoundingCylinder=true; +} + +void Object::ClearBounding(void) +{ + mBoundingBox=false; + mBoundingCylinder=false; +} Signal::Signal() { diff --git a/OpenRoadEd/OpenDrive/ObjectSignal.h b/OpenRoadEd/OpenDrive/ObjectSignal.h index b67d0b998741adacd63986d9b7b9ee3dc2d4548b..a382e0284fbe0fc1e5618a0337d407a563ddf874 100644 --- a/OpenRoadEd/OpenDrive/ObjectSignal.h +++ b/OpenRoadEd/OpenDrive/ObjectSignal.h @@ -3,13 +3,91 @@ #include <string> + +typedef struct +{ + double length; + double width; + double height; +}TBoundingBox; + +typedef struct +{ + double radius; + double height; +}TBoundingCylinder; + +typedef union +{ + TBoundingBox box; + TBoundingCylinder cylinder; +}TBounding; + //*********************************************************************************** //Object //*********************************************************************************** class Object { -public: - Object(){} + private: + double mS; + double mT; + std::string mId; + std::string mName; + bool mDynamic; + std::string mOrientation; + double mZOffset; + double mValidLength; + std::string mType; + std::string mSubType; + double mHeading; + double mPitch; + double mRoll; + bool mBoundingBox; + bool mBoundingCylinder; + TBounding mBounding; + public: + Object(); + Object(std::string &name,std::string &id); + Object(const Object &object); + const Object &operator=(const Object &rhs); + + double GetS(void); + double GetT(void); + std::string GetId(void); + std::string GetName(void); + bool IsDynamic(void); + std::string GetOrientation(void); + double GetZOffset(void); + double GetValidLength(void); + std::string GetType(void); + std::string GetSubType(void); + double GetHeading(void); + double GetPitch(void); + double GetRoll(void); + bool IsBoundigBox(void); + TBoundingBox GetBoundingBox(void); + bool GetBoundingBox(double &length,double &width,double &height); + bool IsBoundigCylinder(void); + TBoundingCylinder GetBoundingCylinder(void); + bool GetBoundingCylinder(double &radius,double &height); + + void SetS(const double s); + void SetT(const double t); + void SetId(const std::string &id); + void SetName(const std::string &name); + void SetDynamic(const bool dynamic); + void SetOrientation(const std::string &orientation); + void SetZOffset(const double zOffset); + void SetValidLength(const double length); + void SetType(const std::string &type); + void SetSubType(const std::string &subType); + void SetHeading(const double heading); + void SetPitch(const double pitch); + void SetRoll(const double roll); + void SetBoundingBox(double length,double width,double height); + void SetBoundingCylinder(double radius,double height); + void ClearBounding(void); + }; //---------------------------------------------------------------------------------- diff --git a/OpenRoadEd/OpenDrive/OpenDriveXmlParser.cpp b/OpenRoadEd/OpenDrive/OpenDriveXmlParser.cpp index 481f08d033d5b38d1273fc5ce0351de368550a2d..78231591b37b14452fbaaa1d970e0316c13d626a 100644 --- a/OpenRoadEd/OpenDrive/OpenDriveXmlParser.cpp +++ b/OpenRoadEd/OpenDrive/OpenDriveXmlParser.cpp @@ -856,6 +856,72 @@ bool OpenDriveXmlParser::ReadLaneHeight(Lane* lane, TiXmlElement *node) bool OpenDriveXmlParser::ReadObjects (Road* road, TiXmlElement *node) { + double s,t,zOffset,validLength,length,width,height,radius,heading,pitch,roll; + std::string id,name,dynamic,orientation,type,subType; + Object *object; + int checker=TIXML_SUCCESS; + TiXmlElement *object_node; + + object_node=node->FirstChildElement("object"); + while(object_node!=0) + { + checker=TIXML_SUCCESS; + checker+=object_node->QueryDoubleAttribute("s",&s); + checker+=object_node->QueryDoubleAttribute("t",&t); + checker+=object_node->QueryStringAttribute("id",&id); + checker+=object_node->QueryStringAttribute("name",&name); + checker+=object_node->QueryStringAttribute("dynamic",&dynamic); + checker+=object_node->QueryStringAttribute("orientation",&orientation); + checker+=object_node->QueryDoubleAttribute("zOffset",&zOffset); + checker+=object_node->QueryDoubleAttribute("validLength",&validLength); + checker+=object_node->QueryStringAttribute("type",&type); + checker+=object_node->QueryStringAttribute("subtype",&subType); + checker+=object_node->QueryDoubleAttribute("hdg",&heading); + checker+=object_node->QueryDoubleAttribute("pitch",&pitch); + checker+=object_node->QueryDoubleAttribute("roll",&roll); + if (checker!=TIXML_SUCCESS) + { + cout<<"Error parsing road object attributes"<<endl; + return false; + } + + std::cout << "read object " << name << " with id: " << id << std::endl; + road->AddObject(); + object=road->GetLastObject(); + object->SetS(s); + object->SetT(t); + object->SetId(id); + object->SetName(name); + if(dynamic=="yes") + object->SetDynamic(true); + else + object->SetDynamic(false); + object->SetOrientation(orientation); + object->SetZOffset(zOffset); + object->SetValidLength(validLength); + object->SetType(type); + object->SetSubType(subType); + object->SetHeading(heading); + object->SetPitch(pitch); + object->SetRoll(roll); + // read bounding box + checker=TIXML_SUCCESS; + checker+=object_node->QueryDoubleAttribute("length",&length); + checker+=object_node->QueryDoubleAttribute("width",&width); + checker+=object_node->QueryDoubleAttribute("height",&height); + if(checker==TIXML_SUCCESS) + object->SetBoundingBox(length,width,height); + else + { + checker=TIXML_SUCCESS; + checker+=object_node->QueryDoubleAttribute("radius",&radius); + checker+=object_node->QueryDoubleAttribute("height",&height); + if(checker==TIXML_SUCCESS) + object->SetBoundingCylinder(radius,height); + } + + object_node=node->NextSiblingElement("object"); + } return true; } //-------------- diff --git a/OpenRoadEd/OpenDrive/OpenDriveXmlWriter.cpp b/OpenRoadEd/OpenDrive/OpenDriveXmlWriter.cpp index 12f5763958987843506912c4a3167cbf1d72442b..07dcf3c669578a79a71576a3d26c6657a9dc0995 100644 --- a/OpenRoadEd/OpenDrive/OpenDriveXmlWriter.cpp +++ b/OpenRoadEd/OpenDrive/OpenDriveXmlWriter.cpp @@ -839,8 +839,67 @@ bool OpenDriveXmlWriter::WriteLaneHeight(TiXmlElement *node, LaneHeight* laneHei bool OpenDriveXmlWriter::WriteObjects (TiXmlElement *node, Road* road) { + bool dynamic; + double length,width,height,radius; TiXmlElement* nodeObjects = new TiXmlElement("objects"); node->LinkEndChild(nodeObjects); + std::stringstream text; + + unsigned int objectCount = road->GetObjectCount(); + for(unsigned int i=0; i<objectCount; i++) + { + Object *object=road->GetObject(i); + + TiXmlElement *object_node = new TiXmlElement("object"); + nodeObjects->LinkEndChild(object_node); + + text << setprecision(16) << setiosflags (ios_base::scientific) << object->GetS(); + object_node->SetAttribute("s",text.str()); + text.str(""); + text << setprecision(16) << setiosflags (ios_base::scientific) << object->GetT(); + object_node->SetAttribute("t",text.str()); + object_node->SetAttribute("id",object->GetId()); + object_node->SetAttribute("name",object->GetName()); + if(object->IsDynamic()) + object_node->SetAttribute("dynamic","yes"); + else + object_node->SetAttribute("dynamic","no"); + object_node->SetAttribute("orientation",object->GetOrientation()); + text.str(""); + text << setprecision(16) << setiosflags (ios_base::scientific) << object->GetZOffset(); + object_node->SetAttribute("zOffset",text.str()); + text.str(""); + text << setprecision(16) << setiosflags (ios_base::scientific) << object->GetValidLength(); + object_node->SetAttribute("validLength",text.str()); + object_node->SetAttribute("type",object->GetType()); + object_node->SetAttribute("subtype",object->GetSubType()); + object_node->SetAttribute("hdg",object->GetHeading()); + object_node->SetAttribute("pitch",object->GetPitch()); + object_node->SetAttribute("roll",object->GetRoll()); + if(object->GetBoundingBox(length,width,height)) + { + text.str(""); + text << setprecision(16) << setiosflags (ios_base::scientific) << length; + object_node->SetAttribute("length",text.str()); + text.str(""); + text << setprecision(16) << setiosflags (ios_base::scientific) << width; + object_node->SetAttribute("width",text.str()); + text.str(""); + text << setprecision(16) << setiosflags (ios_base::scientific) << height; + object_node->SetAttribute("height",text.str()); + } + else if(object->GetBoundingCylinder(radius,height)) + { + text.str(""); + text << setprecision(16) << setiosflags (ios_base::scientific) << radius; + object_node->SetAttribute("radius",text.str()); + text.str(""); + text << setprecision(16) << setiosflags (ios_base::scientific) << height; + object_node->SetAttribute("height",text.str()); + } + + std::cout << "written object " << object->GetName() << " with id: " << object->GetId() << std::endl; + } return true; } diff --git a/OpenRoadEd/OpenDrive/Road.cpp b/OpenRoadEd/OpenDrive/Road.cpp index 4c38b55d5ec42f0f3f29537ab6699ff502a223b9..94a7bf80eb51bc42617b817f007537a0d76b8bf4 100644 --- a/OpenRoadEd/OpenDrive/Road.cpp +++ b/OpenRoadEd/OpenDrive/Road.cpp @@ -789,10 +789,10 @@ unsigned int Road::CloneObject(unsigned int index) { // Check the first method in the group for details - if(index<mSignalsVector.size()-1) - mSignalsVector.insert(mSignalsVector.begin()+index+1, mSignalsVector[index]); - else if(index==mSignalsVector.size()-1) - mSignalsVector.push_back(mSignalsVector[index]); + if(index<mObjectsVector.size()-1) + mObjectsVector.insert(mObjectsVector.begin()+index+1, mObjectsVector[index]); + else if(index==mObjectsVector.size()-1) + mObjectsVector.push_back(mObjectsVector[index]); mLastAddedObject=index+1; return mLastAddedObject; } diff --git a/OpenRoadEd/Osg/OSGRecordsHelpers.cpp b/OpenRoadEd/Osg/OSGRecordsHelpers.cpp index e6771e7b2c2b195986e624aca64854137063d4fa..2943ff5bc98626f5e298a985da96743264b8c254 100644 --- a/OpenRoadEd/Osg/OSGRecordsHelpers.cpp +++ b/OpenRoadEd/Osg/OSGRecordsHelpers.cpp @@ -6,6 +6,7 @@ #include <osg/Geometry> #include <osgDB/ReadFile> #include <osg/Texture2D> +#include <osg/ShapeDrawable> #include "OSGConstants.h" @@ -254,30 +255,11 @@ void OSGRecordsHelpers::FillHelperGroups (Road *road,unsigned int roadIndex, osg } } ////Objects and Signals - //for (unsigned int i = 0; i<road->GetObjectCount(); i++) - //{ - // iconName="Resources/Billboards/Object.jpg"; - // mObjectGroup->addChild(AddRecordHelper(road->GetObject(i)->GetS(),tmpOffset*-6 ,0,OBJECT_NODE,iconName).get())); - //} - // + for (unsigned int i = 0; i<road->GetObjectCount(); i++) + mObjectGroup->addChild(AddObjectHelper(road->GetObject(i)).get()); + for (unsigned int i = 0; i<road->GetSignalCount(); i++) - { - double extra_heading; - std::string type=road->GetSignal(i)->GetType(),sub_type=road->GetSignal(i)->GetSubType(); - std::stringstream icon_name; - - icon_name << "Resources/Billboards/" << type; - if(sub_type!="-1" && sub_type!="none") - icon_name << "_" << sub_type << ".jpg"; - else - icon_name << ".jpg"; - iconName=icon_name.str(); - if(road->GetSignal(i)->GetOrientation()=="+") - extra_heading=0.0; - else - extra_heading=3.14159; - mSignalGroup->addChild(AddRecordHelper(road->GetSignal(i)->GetS(),0,road->GetSignal(i)->GetT(),0,SIGNAL_NODE,iconName,extra_heading).get()); - } + mSignalGroup->addChild(AddSignalHelper(road->GetSignal(i)).get()); } /** @@ -295,7 +277,6 @@ osg::ref_ptr<osg::MatrixTransform> OSGRecordsHelpers::AddRecordHelper(double s, osg::ref_ptr<osg::MatrixTransform> matrix = new osg::MatrixTransform; matrix->setName("RecordMatrix"); - //Get the coords and the heading for the current record double x,y,hdg,elevation; short int resultID=mRoad->GetGeometryCoords(s,x,y,hdg); @@ -305,41 +286,30 @@ osg::ref_ptr<osg::MatrixTransform> OSGRecordsHelpers::AddRecordHelper(double s, elevation=mRoad->GetElevationValue(s); - - //========================================================= - //Ad an arrow - //========================================================= - osg::ref_ptr<OSGGeodeNode> arrowGeode = new OSGGeodeNode(); - osg::ref_ptr<osg::Geometry> arrowGeom=new osg::Geometry; - arrowGeom->setUseDisplayList( false ); - - arrowGeode->addDrawable(arrowGeom); - if(type==SIGNAL_NODE) + //========================================================= + //Ad an arrow + //========================================================= + osg::ref_ptr<OSGGeodeNode> arrowGeode = new OSGGeodeNode(); + osg::ref_ptr<osg::Geometry> arrowGeom=new osg::Geometry; + arrowGeom->setUseDisplayList( false ); + + arrowGeode->addDrawable(arrowGeom); + arrowGeom->setVertexArray( mArrowVertices.get() ); + arrowGeom->addPrimitiveSet(mArrowTris.get()); + + osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array; + arrowGeom->setColorArray(colors.get()); + arrowGeom->setColorBinding(osg::Geometry::BIND_OVERALL); + if (color!=NULL) { - arrowGeom->setVertexArray( mSignalArrowVertices.get() ); - arrowGeom->addPrimitiveSet(mSignalArrowTris.get()); - } + colors->push_back(*color); + } else - { - arrowGeom->setVertexArray( mArrowVertices.get() ); - arrowGeom->addPrimitiveSet(mArrowTris.get()); - } + colors->push_back(osg::Vec4(0.8f, 0.8f, 0.8f, 1.0f) ); - osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array; - arrowGeom->setColorArray(colors.get()); - arrowGeom->setColorBinding(osg::Geometry::BIND_OVERALL); - if (color!=NULL) - { - colors->push_back(*color); - } - else - colors->push_back(osg::Vec4(0.8f, 0.8f, 0.8f, 1.0f) ); - - arrowGeom->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); - - - arrowGeode->SetNodeType(type); + arrowGeom->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + arrowGeode->SetNodeType(type); //========================================================= //Now, add a billboard with the texture of the needed type @@ -348,7 +318,7 @@ osg::ref_ptr<osg::MatrixTransform> OSGRecordsHelpers::AddRecordHelper(double s, billboardIcon->SetNodeType(type); - if(type==SIGNAL_NODE) + if(type==SIGNAL_NODE || type==OBJECT_NODE) billboardIcon->addDrawable(mSignalBillboard); else billboardIcon->addDrawable(mBillboard); @@ -362,7 +332,7 @@ osg::ref_ptr<osg::MatrixTransform> OSGRecordsHelpers::AddRecordHelper(double s, osg::Image *billboardIconImage = osgDB::readImageFile(iconName); if (!billboardIconImage) { - billboardIconImage = osgDB::readImageFile("Resources/Signal.jpg"); + billboardIconImage = osgDB::readImageFile("Resources/noTexture.jpg"); if (!billboardIconImage) { return matrix.get(); @@ -378,45 +348,231 @@ osg::ref_ptr<osg::MatrixTransform> OSGRecordsHelpers::AddRecordHelper(double s, stateSet->setTextureAttributeAndModes(0, roadTexture, osg::StateAttribute::ON); //stateSet->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); - //=========================================================================================== //in order to translate the helper orthogonally to the heading, compute the cos and sin //=========================================================================================== - if(type==SIGNAL_NODE) + double difX=cos(hdg+M_PI_2)*offsetX; + double difY=sin(hdg+M_PI_2)*offsetX; + + double dif2X=cos(hdg)*mSize; + double dif2Y=sin(hdg)*mSize; + + matrix->setMatrix( osg::Matrix::rotate(osg::inRadians(hdg-M_PI_2), osg::Vec3(0.0, 0.0, 1.0)) * + //osg::Matrix::translate(osg::Vec3(x+difX,y+difY,elevation+ROADMARK_ELEVATION_SHIFT+mVerticalOffset+offsetZ)) ); + osg::Matrix::translate(osg::Vec3(x+difX+dif2X,y+difY+dif2Y,elevation+ROADMARK_ELEVATION_SHIFT+mVerticalOffset+offsetZ)) ); + + matrix->addChild(arrowGeode); + matrix->addChild(billboardIcon); + + return matrix; +} + +osg::ref_ptr<osg::MatrixTransform> OSGRecordsHelpers::AddObjectHelper(Object *object) +{ + osg::ref_ptr<OSGGeodeNode> ShapeGeode = new OSGGeodeNode(); + osg::ref_ptr<osg::ShapeDrawable> Shape = new osg::ShapeDrawable; + osg::ref_ptr<osg::MatrixTransform> matrix = new osg::MatrixTransform; + matrix->setName("RecordMatrix"); + + //Get the coords and the heading for the current record + double x,y,hdg,elevation,s; + s=object->GetS(); + short int resultID=mRoad->GetGeometryCoords(s,x,y,hdg); + + if (resultID==-999) + return matrix; + + elevation=mRoad->GetElevationValue(s); + + //========================================================= + //Now, add a billboard with the texture of the needed type + //========================================================= + osg::ref_ptr<OSGBillboardNode> billboardIcon = new OSGBillboardNode; + + billboardIcon->SetNodeType(OBJECT_NODE); + + double length,width,height,radius; + + if(object->GetBoundingBox(length,width,height)) { - double heading; - - x-=offsetY*sin(hdg); - y+=offsetY*cos(hdg); - heading=hdg+extra_heading; - if(heading>2*3.14159) - heading-=2*3.14159; - matrix->setMatrix( osg::Matrix::rotate(osg::inRadians(heading-M_PI_2), osg::Vec3(0.0, 0.0, 1.0)) * - osg::Matrix::translate(osg::Vec3(x,y,elevation+ROADMARK_ELEVATION_SHIFT+mVerticalOffset+offsetZ)) ); + Shape->setShape(new osg::Box(osg::Vec3(0.0,0.0,0.0),length,width,height)); + Shape->setColor(osg::Vec4(0.2f, 0.2f, 0.2f, 1.0f)); + + ShapeGeode->addDrawable(Shape); + ShapeGeode->SetNodeType(OBJECT_NODE); + } + else if(object->GetBoundingCylinder(radius,height)) + { + Shape->setShape(new osg::Cylinder(osg::Vec3(0.0,0.0,0.0),radius,height)); + Shape->setColor(osg::Vec4(0.2f, 0.2f, 0.2f, 1.0f)); + + ShapeGeode->addDrawable(Shape); + ShapeGeode->SetNodeType(OBJECT_NODE); } else { - double difX=cos(hdg+M_PI_2)*offsetX; - double difY=sin(hdg+M_PI_2)*offsetX; + billboardIcon->addDrawable(mSignalBillboard); + billboardIcon->setMode(osg::Billboard::POINT_ROT_EYE); + billboardIcon->setNormal(osg::Vec3(0.0f,-1.0f,0.0f)); - double dif2X=cos(hdg)*mSize; - double dif2Y=sin(hdg)*mSize; + osg::StateSet* stateSet= billboardIcon->getOrCreateStateSet(); + // create a texture + // load image for texture + std::string type=object->GetType(),iconName; + std::stringstream icon_name; + + icon_name << "Resources/Billboards/" << type << ".jpg"; + iconName=icon_name.str(); + osg::Image *billboardIconImage = osgDB::readImageFile(iconName); + if (!billboardIconImage) + { + billboardIconImage = osgDB::readImageFile("Resources/Billboards/Object.jpg"); + if (!billboardIconImage) + return matrix.get(); + } + osg::ref_ptr<osg::Texture2D> roadTexture = new osg::Texture2D; + roadTexture->setDataVariance(osg::Object::DYNAMIC); + roadTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); + roadTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); + roadTexture->setImage(billboardIconImage); + + // assign the material and texture + stateSet->setTextureAttributeAndModes(0, roadTexture, osg::StateAttribute::ON); + //stateSet->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); + } + //=========================================================================================== + //in order to translate the helper orthogonally to the heading, compute the cos and sin + //=========================================================================================== + x-=object->GetT()*sin(hdg); + y+=object->GetT()*cos(hdg); + + if(object->IsBoundigBox()) + { + matrix->setMatrix(osg::Matrix::rotate(osg::inRadians(hdg+object->GetHeading()-M_PI_2), osg::Vec3(0.0, 0.0, 1.0)) * + osg::Matrix::translate(osg::Vec3(x,y,elevation+object->GetZOffset())) ); + matrix->addChild(ShapeGeode); + } + else if(object->IsBoundigCylinder()) + { + matrix->setMatrix(osg::Matrix::rotate(osg::inRadians(hdg+object->GetHeading()-M_PI_2), osg::Vec3(0.0, 0.0, 1.0)) * + osg::Matrix::translate(osg::Vec3(x,y,elevation+object->GetZOffset())) ); + matrix->addChild(ShapeGeode); + } + else + { matrix->setMatrix( osg::Matrix::rotate(osg::inRadians(hdg-M_PI_2), osg::Vec3(0.0, 0.0, 1.0)) * - //osg::Matrix::translate(osg::Vec3(x+difX,y+difY,elevation+ROADMARK_ELEVATION_SHIFT+mVerticalOffset+offsetZ)) ); - osg::Matrix::translate(osg::Vec3(x+difX+dif2X,y+difY+dif2Y,elevation+ROADMARK_ELEVATION_SHIFT+mVerticalOffset+offsetZ)) ); + osg::Matrix::translate(osg::Vec3(x,y,elevation+ROADMARK_ELEVATION_SHIFT+mVerticalOffset+object->GetZOffset()))); + matrix->addChild(billboardIcon); } + return matrix; +} + +osg::ref_ptr<osg::MatrixTransform> OSGRecordsHelpers::AddSignalHelper(Signal *signal) +{ + osg::ref_ptr<OSGGeodeNode> arrowGeode = new OSGGeodeNode(); + osg::ref_ptr<osg::Geometry> arrowGeom=new osg::Geometry; + osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array; + osg::ref_ptr<osg::MatrixTransform> matrix = new osg::MatrixTransform; + matrix->setName("RecordMatrix"); + + //Get the coords and the heading for the current record + double x,y,hdg,elevation,s; + s=signal->GetS(); + short int resultID=mRoad->GetGeometryCoords(s,x,y,hdg); + + if (resultID==-999) + return matrix; + + elevation=mRoad->GetElevationValue(s); + + //========================================================= + //Ad an arrow + //========================================================= + if(signal->GetOrientation()!="none") + { + arrowGeom->setUseDisplayList( false ); + + arrowGeode->addDrawable(arrowGeom); + arrowGeom->setVertexArray( mSignalArrowVertices.get() ); + arrowGeom->addPrimitiveSet(mSignalArrowTris.get()); + + arrowGeom->setColorArray(colors.get()); + arrowGeom->setColorBinding(osg::Geometry::BIND_OVERALL); + colors->push_back(osg::Vec4(0.8f, 0.8f, 0.8f, 1.0f) ); + + arrowGeom->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + + arrowGeode->SetNodeType(SIGNAL_NODE); + } + + //========================================================= + //Now, add a billboard with the texture of the needed type + //========================================================= + osg::ref_ptr<OSGBillboardNode> billboardIcon = new OSGBillboardNode; + + billboardIcon->SetNodeType(SIGNAL_NODE); + + billboardIcon->addDrawable(mSignalBillboard); + billboardIcon->setMode(osg::Billboard::POINT_ROT_EYE); + billboardIcon->setNormal(osg::Vec3(0.0f,-1.0f,0.0f)); - matrix->addChild(arrowGeode); + osg::StateSet* stateSet= billboardIcon->getOrCreateStateSet(); + // create a texture + // load image for texture + std::string type=signal->GetType(),sub_type=signal->GetSubType(),iconName; + std::stringstream icon_name; + + icon_name << "Resources/Billboards/" << type; + if(sub_type!="-1" && sub_type!="none") + icon_name << "_" << sub_type << ".jpg"; + else + icon_name << ".jpg"; + iconName=icon_name.str(); + osg::Image *billboardIconImage = osgDB::readImageFile(iconName); + if (!billboardIconImage) + { + billboardIconImage = osgDB::readImageFile("Resources/Billboards/Signal.jpg"); + if (!billboardIconImage) + { + return matrix.get(); + } + } + osg::ref_ptr<osg::Texture2D> roadTexture = new osg::Texture2D; + roadTexture->setDataVariance(osg::Object::DYNAMIC); + roadTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); + roadTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); + roadTexture->setImage(billboardIconImage); + + // assign the material and texture + stateSet->setTextureAttributeAndModes(0, roadTexture, osg::StateAttribute::ON); + //stateSet->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); + + //=========================================================================================== + //in order to translate the helper orthogonally to the heading, compute the cos and sin + //=========================================================================================== + double heading; + + x-=signal->GetT()*sin(hdg); + y+=signal->GetT()*cos(hdg); + if(signal->GetOrientation()=="+") + heading=hdg; + else + heading=hdg+3.14159; + if(heading>2*3.14159) + heading-=2*3.14159; + matrix->setMatrix( osg::Matrix::rotate(osg::inRadians(heading-M_PI_2), osg::Vec3(0.0, 0.0, 1.0)) * + osg::Matrix::translate(osg::Vec3(x,y,elevation+ROADMARK_ELEVATION_SHIFT+mVerticalOffset+signal->GetZOffset()))); + + if(signal->GetOrientation()!="none") + matrix->addChild(arrowGeode); matrix->addChild(billboardIcon); return matrix; } //-------------- - - void OSGRecordsHelpers::CreateBillboard() { mBillboard = new osg::Geometry(); diff --git a/OpenRoadEd/Osg/OSGRecordsHelpers.h b/OpenRoadEd/Osg/OSGRecordsHelpers.h index 697601b5a0be8d8798ba1dc3d8274f1b9eb5634b..1f59b7010a9cdc27b034c4fa80b3c423c707eac3 100644 --- a/OpenRoadEd/Osg/OSGRecordsHelpers.h +++ b/OpenRoadEd/Osg/OSGRecordsHelpers.h @@ -51,6 +51,8 @@ private: * @param color Color of the glyph. Used to distinguish between the left and right lane records */ osg::ref_ptr<osg::MatrixTransform> AddRecordHelper(double s, double offsetX,double offsetY,double offsetZ, OSGNodeType type, std::string iconName, double extra_heading=0.0,osg::Vec4* color=NULL); + osg::ref_ptr<osg::MatrixTransform> AddObjectHelper(Object *object); + osg::ref_ptr<osg::MatrixTransform> AddSignalHelper(Signal *signal); public: OSGRecordsHelpers(); diff --git a/OpenRoadEd/Qt/CreationWidgets/CreationAllRoad.cpp b/OpenRoadEd/Qt/CreationWidgets/CreationAllRoad.cpp index 2b732a184ca08d032c917ff77a92d7f1e0c1b9a2..27b20a6cebb4925dca8f157c91e06f6dccde9ae8 100644 --- a/OpenRoadEd/Qt/CreationWidgets/CreationAllRoad.cpp +++ b/OpenRoadEd/Qt/CreationWidgets/CreationAllRoad.cpp @@ -634,7 +634,47 @@ void CreationAllRoad::CreateLaneSectionPressed() void CreationAllRoad::CreateObjectPressed() { // Not implemented yet + Road *lRoad=NULL; + Object *lObject=NULL; + unsigned int index=0; + + // Get the current selection + Selection *lCurSelection = mRoadTree->GetSelection(); + RoadTreeItemType lType = lCurSelection->GetType(); + // If another road type is selected - duplicate it + if(lType == OBJECT) + { + // Clone the selected road type + lRoad = mRoadTree->GetRealRoad(); + index = lRoad->CloneObject((*lCurSelection)[1]); + // Redraws the road to reflect the changes + mOsgMain->RedrawRoad(lCurSelection->GetIndex(0)); + // Add new road type to the road tree + mRoadTree->AddObject((*lCurSelection)[0], index, true); + //emit RoadChanged(false); + } + // If something else is selected - duplicate the last road type or create a new one if + // no road types exist + else if(lType == ROAD || lType == ROAD_TYPE_CONTAINER || (lType>ROAD && lType<CONTROLLER_CONTAINER)) + { + // Get last road type + lRoad = mRoadTree->GetRealRoad(); + lObject = lRoad->GetLastObject(); + // Duplicate it if it exists + if(lObject) index = lRoad->CloneObject(lRoad->GetObjectCount()-1); + // else create a blank one + else index = lRoad->AddObject(); + // Redraws the road to reflect the changes + mOsgMain->RedrawRoad(lCurSelection->GetIndex(0)); + // Add new road type to the road tree + mRoadTree->AddObject((*lCurSelection)[0], index, true); + //emit RoadChanged(false); + } + + // Cleares the keyboard focus, so pressing space to switch to camera mode won't create a record + mCreateObject->clearFocus(); } + void CreationAllRoad::CreateSignalPressed() { // Not implemented yet @@ -665,7 +705,7 @@ void CreationAllRoad::CreateSignalPressed() lRoad = mRoadTree->GetRealRoad(); lSignal = lRoad->GetLastSignal(); // Duplicate it if it exists - if(lSignal) index = lRoad->CloneSignal(lRoad->GetRoadTypeCount()-1); + if(lSignal) index = lRoad->CloneSignal(lRoad->GetSignalCount()-1); // else create a blank one else index = lRoad->AddSignal(); // Redraws the road to reflect the changes diff --git a/OpenRoadEd/Qt/SettingsWidgets/SettingsPage.cpp b/OpenRoadEd/Qt/SettingsWidgets/SettingsPage.cpp index d4d1dd37c6945ff53eed922447a369ea0379dc07..a58cae9f859b33786632cdeafd9ed1ef69aef182 100644 --- a/OpenRoadEd/Qt/SettingsWidgets/SettingsPage.cpp +++ b/OpenRoadEd/Qt/SettingsWidgets/SettingsPage.cpp @@ -22,6 +22,8 @@ SettingsPage::SettingsPage(OpenDrive *openDrive,RoadTree *roadTree) mRoad->hide(); mRoadSignal = new SettingsRoadSignal(mOpenDrive); mRoadSignal->hide(); + mRoadObject = new SettingsRoadObject(mOpenDrive); + mRoadObject->hide(); mRoadType = new SettingsRoadTypeRecord; mRoadType->hide(); mGeometryLine = new SettingsGeometryLine; @@ -92,6 +94,7 @@ SettingsPage::SettingsPage(OpenDrive *openDrive,RoadTree *roadTree) mainLayout->addWidget(mJunctionPriority); mainLayout->addWidget(mJunctionController); // ADD OBJECT HERE + mainLayout->addWidget(mRoadObject); // ADD SIGNAL HERE mainLayout->addWidget(mRoadSignal); // ADD CONTROLLER HERE @@ -118,6 +121,7 @@ SettingsPage::SettingsPage(OpenDrive *openDrive,RoadTree *roadTree) connect(mLaneHeight, SIGNAL(RoadLaneHeightChanged(bool)), this, SLOT(OnRoadGeometryChanged(bool))); connect(mJunctionLaneLink, SIGNAL(RoadGeometryChanged(bool)), this, SLOT(OnRoadGeometryChanged(bool))); connect(mRoadSignal, SIGNAL(RoadGeometryChanged(bool)), this, SLOT(OnRoadGeometryChanged(bool))); + connect(mRoadObject, SIGNAL(RoadGeometryChanged(bool)), this, SLOT(OnRoadGeometryChanged(bool))); connect(mJunctionLaneLink, SIGNAL(RoadChanged(unsigned int)), this, SLOT(OnRoadChanged(unsigned int))); connect(mJunction, SIGNAL(RoadChanged(unsigned int)), this, SLOT(OnRoadChanged(unsigned int))); } @@ -150,6 +154,7 @@ void SettingsPage::HideAll() mJunctionPriority->hide(); mJunctionController->hide(); // ADD OBJECT HERE + mRoadObject->hide(); // ADD SIGNAL HERE mRoadSignal->hide(); // ADD CONTROLLER HERE @@ -302,8 +307,8 @@ void SettingsPage::OnObjectSelected(Object *node) // See the first few methods in this group for details HideAll(); - //mObject->show(); - //mObject->LoadData(node); + mRoadObject->show(); + mRoadObject->LoadData(node); } void SettingsPage::OnSignalSelected(Signal *node) { diff --git a/OpenRoadEd/Qt/SettingsWidgets/SettingsPage.h b/OpenRoadEd/Qt/SettingsWidgets/SettingsPage.h index 44df9e8dbdd2f94684dfe1b9c01e84495ca30418..243edd3db927cced8ca980e53bc3764d6fa7a0c2 100644 --- a/OpenRoadEd/Qt/SettingsWidgets/SettingsPage.h +++ b/OpenRoadEd/Qt/SettingsWidgets/SettingsPage.h @@ -10,6 +10,7 @@ #include "SettingsRoad.h" #include "SettingsRoadSignal.h" +#include "SettingsRoadObject.h" #include "SettingsRoadTypeRecord.h" #include "SettingsGeometryLine.h" #include "SettingsGeometryTurn.h" @@ -62,6 +63,7 @@ private: */ SettingsRoad *mRoad; SettingsRoadSignal *mRoadSignal; + SettingsRoadObject *mRoadObject; SettingsRoadTypeRecord *mRoadType; SettingsGeometryLine *mGeometryLine; SettingsGeometryTurn *mGeometryTurn; diff --git a/OpenRoadEd/Qt/SettingsWidgets/SettingsRoadObject.cpp b/OpenRoadEd/Qt/SettingsWidgets/SettingsRoadObject.cpp new file mode 100644 index 0000000000000000000000000000000000000000..afec42159976003a607fd735bc977746e591ddb9 --- /dev/null +++ b/OpenRoadEd/Qt/SettingsWidgets/SettingsRoadObject.cpp @@ -0,0 +1,452 @@ +#include "SettingsRoadObject.h" +#include "moc_SettingsRoadObject.cpp" + +/** + * Initializes the properties panel and the UI elements + */ +SettingsRoadObject::SettingsRoadObject(OpenDrive *openDrive) +{ + // Resets the record + mObject=NULL; + + // Saves a reference to OpenDrive object + mOpenDrive=openDrive; + + // Main vertical layout + QVBoxLayout *mainLayout = new QVBoxLayout; + + //------------------------------------------------- + // Group for settings + QGroupBox *settingsGroup = new QGroupBox; + settingsGroup->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Maximum); + settingsGroup->setTitle(tr("Road object Settings")); + + mName = new QLineEdit; + mId = new QLineEdit; + mS = new QLineEdit; + mT = new QLineEdit; + mDynamic = new QCheckBox; + mDynamic->setCheckable(true); + mDynamic->setChecked(false); + mOrientation = new QComboBox; + mOrientation->insertItem(0,tr("+")); + mOrientation->insertItem(1,tr("-")); + mOrientation->insertItem(2,tr("none")); + mZOffset = new QLineEdit; + mValidLength = new QLineEdit; + mType = new QComboBox; + mType->insertItem(0,tr("none")); + mTypeMap["none"]="-1"; + mType->insertItem(1,tr("obstacle")); + mTypeMap["obstacle"]="0"; + mType->insertItem(2,tr("pole")); + mTypeMap["pole"]="1"; + mType->insertItem(3,tr("tree")); + mTypeMap["tree"]="2"; + mType->insertItem(4,tr("vegetation")); + mTypeMap["vegetation"]="3"; + mType->insertItem(5,tr("barrier")); + mTypeMap["barrier"]="4"; + mType->insertItem(6,tr("building")); + mTypeMap["building"]="5"; + mType->insertItem(7,tr("parkingSpace")); + mTypeMap["parkingSpace"]="6"; + mType->insertItem(8,tr("patch")); + mTypeMap["patch"]="7"; + mType->insertItem(9,tr("railing")); + mTypeMap["railing"]="8"; + mType->insertItem(10,tr("trafficIsland")); + mTypeMap["trafficIsland"]="9"; + mType->insertItem(11,tr("crossWalk")); + mTypeMap["crossWalk"]="10"; + mType->insertItem(12,tr("streetLamp")); + mTypeMap["streetLamp"]="11"; + mType->insertItem(13,tr("gantry")); + mTypeMap["gantry"]="12"; + mType->insertItem(14,tr("soundBarrier")); + mTypeMap["soundBarrier"]="13"; + mType->insertItem(15,tr("unkown")); + mTypeMap["unknown"]="14"; + mSubType = new QLineEdit; + mHeading = new QLineEdit; + + mBoundingBox = new QGroupBox; + mBoundingBox->setTitle(tr("BoundingBox")); + mBoundingBox->setCheckable(true); + mBoundingBox->setChecked(false); + mBoxLength = new QLineEdit; + mBoxLength->setText("0.0"); + mBoxWidth = new QLineEdit; + mBoxWidth->setText("0.0"); + mBoxHeight = new QLineEdit; + mBoxHeight->setText("0.0"); + // Form Layout inside group PREDECESSOR + QFormLayout *settingsBoundingBoxLayout = new QFormLayout; + settingsBoundingBoxLayout->addRow(tr("Box length:"),mBoxLength); + settingsBoundingBoxLayout->addRow(tr("Box width:"),mBoxWidth); + settingsBoundingBoxLayout->addRow(tr("Box height:"),mBoxHeight); + mBoundingBox->setLayout(settingsBoundingBoxLayout); + + mBoundingCyl = new QGroupBox; + mBoundingCyl->setTitle(tr("BoundingCylinder")); + mBoundingCyl->setCheckable(true); + mBoundingCyl->setChecked(false); + mCylRadius = new QLineEdit; + mCylRadius->setText("0.0"); + mCylHeight = new QLineEdit; + mCylHeight->setText("0.0"); + // Form Layout inside group PREDECESSOR + QFormLayout *settingsBoundingCylLayout = new QFormLayout; + settingsBoundingCylLayout->addRow(tr("Cyl radius:"),mCylRadius); + settingsBoundingCylLayout->addRow(tr("Cyl height:"),mCylHeight); + mBoundingCyl->setLayout(settingsBoundingCylLayout); + + // Form Layout inside group + QFormLayout *settingsFormLayout = new QFormLayout; + settingsFormLayout->addRow(tr("Name:"),mName); + settingsFormLayout->addRow(tr("Id:"),mId); + settingsFormLayout->addRow(tr("s:"),mS); + settingsFormLayout->addRow(tr("t:"),mT); + settingsFormLayout->addRow(tr("Dynamic:"),mDynamic); + settingsFormLayout->addRow(tr("Orientation:"),mOrientation); + settingsFormLayout->addRow(tr("zOffset:"),mZOffset); + settingsFormLayout->addRow(tr("validLength:"),mValidLength); + settingsFormLayout->addRow(tr("Type:"),mType); + settingsFormLayout->addRow(tr("SubType:"),mSubType); + settingsFormLayout->addRow(tr("Heading:"),mHeading); + + QVBoxLayout *settingsGroupLayout = new QVBoxLayout; + settingsGroupLayout->addLayout(settingsFormLayout); + settingsGroupLayout->addWidget(mBoundingBox); + settingsGroupLayout->addWidget(mBoundingCyl); + + settingsGroup->setLayout(settingsGroupLayout); + //------------------------------------------------- + // Group for help + QGroupBox *helpGroup = new QGroupBox; + helpGroup->setTitle(tr("Help")); + + QTextEdit *helpText = new QTextEdit; + helpText->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Expanding); + helpText->setReadOnly(true); + helpText->setHtml("This record is the principal containers of information about a object road." + "<p><b>Name</b> - name of the object</p>" + "<p><b>Id</b> - unique identifier of the object (string)</p>" + "<p><b>s</b> - start position (s-offset) [meters]</p>" + "<p><b>t</b> - lateral offset with respect to the center of the road [meters]</p>" + "<p><b>Dynamic</b> - indicates whether the object can change over time (bool)</p>" + "<p><b>Orientation</b> - validity of the object with respect to the road heading. + valid in positive track direction, - valid in negative track direction, none valid in both directions </p>" + "<p><b>zOffset</b> - z offset from track level to bottom edge of the object [meter]</p>" + "<p><b>validLength</b> - extent of object's validity along s-axis (0.0 for point object) [meter]</p>" + "<p><b>Type</b> - type identifier according to country code. -1 or none for unspecified type</p>" + "<p><b>SubType</b> - sub type identifier according to country code. -1 or none for unspecified sub type</p>" + "<p><b>heading</b> - heading angle of the object relative to road direction</p>" + "<p><b>BoundingBox</b> - check if this road has a bounding box</p>" + "<p><b>Box length</b> - length of the bounding box</p>" + "<p><b>Box width</b> - width of the bounding box</p>" + "<p><b>Box height</b> - height of the bounding box</p>" + "<p><b>BoundingCylinder</b> - check if this road has a bounding cylinder</p>" + "<p><b>Cyl radius</b> - radius of the bounding cylinder</p>" + "<p><b>Cyl height</b> - height of the bounding cylinder</p>"); + + QVBoxLayout *helpLayout = new QVBoxLayout; + helpLayout->addWidget(helpText); + + helpGroup->setLayout(helpLayout); + //------------------------------------------------- + + mainLayout->addWidget(settingsGroup); + mainLayout->addWidget(helpGroup); + setLayout(mainLayout); +} + +/** + * Loads the data for a given record + * + * @param road Road record whose properties are to be loaded + */ +void SettingsRoadObject::LoadData(Object *object) +{ + double length,width,height,radius; + + if(object!=NULL) + { + // Disconnects the "value changed" objects while the values are loaded + disconnect(mName, SIGNAL(editingFinished()), this, SLOT(NameChanged())); + disconnect(mId, SIGNAL(editingFinished()), this, SLOT(IdChanged())); + disconnect(mS, SIGNAL(editingFinished()), this, SLOT(SChanged())); + disconnect(mT, SIGNAL(editingFinished()), this, SLOT(TChanged())); + disconnect(mDynamic, SIGNAL(clicked(bool)), this, SLOT(DynamicChanged(bool))); + disconnect(mOrientation, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(OrientationChanged(const QString &))); + disconnect(mZOffset, SIGNAL(editingFinished()), this, SLOT(ZOffsetChanged())); + disconnect(mValidLength, SIGNAL(editingFinished()), this, SLOT(ValidLengthChanged())); + disconnect(mType, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(TypeChanged(const QString &))); + disconnect(mSubType,SIGNAL(editingFinished()), this, SLOT(SubTypeChanged())); + disconnect(mHeading, SIGNAL(editingFinished()), this, SLOT(HeadingChanged())); + disconnect(mBoundingBox, SIGNAL(clicked(bool)), this, SLOT(BoundingBoxChanged(bool))); + disconnect(mBoxLength, SIGNAL(editingFinished()), this, SLOT(BoxLengthChanged())); + disconnect(mBoxWidth, SIGNAL(editingFinished()), this, SLOT(BoxWidthChanged())); + disconnect(mBoxHeight, SIGNAL(editingFinished()), this, SLOT(BoxHeightChanged())); + disconnect(mBoundingCyl, SIGNAL(clicked(bool)), this, SLOT(BoundingCylChanged(bool))); + disconnect(mCylRadius, SIGNAL(editingFinished()), this, SLOT(CylRadiusChanged())); + disconnect(mCylHeight, SIGNAL(editingFinished()), this, SLOT(CylHeightChanged())); + + // Sets the record properties to the input widgets + mObject=object; + + mName->setText(object->GetName().c_str()); + mId->setText(object->GetId().c_str()); + mS->setText(QString("%1").arg(object->GetS())); + mT->setText(QString("%1").arg(object->GetT())); + if(object->IsDynamic()) + mDynamic->setChecked(true); + else + mDynamic->setChecked(false); + if(object->GetOrientation()=="+") + mOrientation->setCurrentIndex(0); + else if(object->GetOrientation()=="-") + mOrientation->setCurrentIndex(1); + else + mOrientation->setCurrentIndex(2); + mZOffset->setText(QString("%1").arg(object->GetZOffset())); + mValidLength->setText(QString("%1").arg(object->GetValidLength())); + if(object->GetType()=="-1" || object->GetType()=="none") + mType->setCurrentIndex(0); + else if(object->GetType()=="obstacle") + mType->setCurrentIndex(1); + else if(object->GetType()=="pole") + mType->setCurrentIndex(2); + else if(object->GetType()=="tree") + mType->setCurrentIndex(3); + else if(object->GetType()=="vegetation") + mType->setCurrentIndex(4); + else if(object->GetType()=="barrier") + mType->setCurrentIndex(5); + else if(object->GetType()=="building") + mType->setCurrentIndex(6); + else if(object->GetType()=="parkingSpace") + mType->setCurrentIndex(7); + else if(object->GetType()=="patch") + mType->setCurrentIndex(8); + else if(object->GetType()=="railing") + mType->setCurrentIndex(9); + else if(object->GetType()=="trafficIsland") + mType->setCurrentIndex(10); + else if(object->GetType()=="crossWalk") + mType->setCurrentIndex(11); + else if(object->GetType()=="streetLamp") + mType->setCurrentIndex(12); + else if(object->GetType()=="gantry") + mType->setCurrentIndex(13); + else if(object->GetType()=="soundBarrier") + mType->setCurrentIndex(14); + else + mType->setCurrentIndex(15); + mSubType->setText(object->GetSubType().c_str()); + mHeading->setText(QString("%1").arg(object->GetHeading())); + + if(object->GetBoundingBox(length,width,height)) + { + mBoundingBox->setChecked(true); + mBoundingCyl->setChecked(false); + mBoxLength->setText(QString("%1").arg(length)); + mBoxWidth->setText(QString("%1").arg(width)); + mBoxHeight->setText(QString("%1").arg(height)); + } + else if(object->GetBoundingCylinder(radius,height)) + { + mBoundingBox->setChecked(false); + mBoundingCyl->setChecked(true); + mCylRadius->setText(QString("%1").arg(radius)); + mCylHeight->setText(QString("%1").arg(height)); + } + else + { + mBoundingBox->setChecked(false); + mBoundingCyl->setChecked(false); + } + + connect(mName, SIGNAL(editingFinished()), this, SLOT(NameChanged())); + connect(mId, SIGNAL(editingFinished()), this, SLOT(IdChanged())); + connect(mS, SIGNAL(editingFinished()), this, SLOT(SChanged())); + connect(mT, SIGNAL(editingFinished()), this, SLOT(TChanged())); + connect(mDynamic, SIGNAL(clicked(bool)), this, SLOT(DynamicChanged(bool))); + connect(mOrientation, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(OrientationChanged(const QString &))); + connect(mZOffset, SIGNAL(editingFinished()), this, SLOT(ZOffsetChanged())); + connect(mValidLength, SIGNAL(editingFinished()), this, SLOT(ValidLengthChanged())); + connect(mType, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(TypeChanged(const QString &))); + connect(mSubType,SIGNAL(editingFinished()), this, SLOT(SubTypeChanged())); + connect(mHeading, SIGNAL(editingFinished()), this, SLOT(HeadingChanged())); + connect(mBoundingBox, SIGNAL(clicked(bool)), this, SLOT(BoundingBoxChanged(bool))); + connect(mBoxLength, SIGNAL(editingFinished()), this, SLOT(BoxLengthChanged())); + connect(mBoxWidth, SIGNAL(editingFinished()), this, SLOT(BoxWidthChanged())); + connect(mBoxHeight, SIGNAL(editingFinished()), this, SLOT(BoxHeightChanged())); + connect(mBoundingCyl, SIGNAL(clicked(bool)), this, SLOT(BoundingCylChanged(bool))); + connect(mCylRadius, SIGNAL(editingFinished()), this, SLOT(CylRadiusChanged())); + connect(mCylHeight, SIGNAL(editingFinished()), this, SLOT(CylHeightChanged())); + } +} + +/** + * Methods called when properties change + */ +void SettingsRoadObject::NameChanged() +{ + // Sets the new value + mObject->SetName(mName->text().toStdString()); +} + +void SettingsRoadObject::IdChanged() +{ + mObject->SetId(mId->text().toStdString()); +} + +void SettingsRoadObject::SChanged() +{ + mObject->SetS(mS->text().toDouble()); + emit RoadGeometryChanged(true); +} + +void SettingsRoadObject::TChanged() +{ + mObject->SetT(mT->text().toDouble()); + emit RoadGeometryChanged(true); +} + +void SettingsRoadObject::DynamicChanged(bool on) +{ + mObject->SetDynamic(on); +} + +void SettingsRoadObject::OrientationChanged(const QString & text) +{ + mObject->SetOrientation(text.toStdString()); + emit RoadGeometryChanged(true); +} + +void SettingsRoadObject::ZOffsetChanged() +{ + mObject->SetZOffset(mZOffset->text().toDouble()); + emit RoadGeometryChanged(true); +} + +void SettingsRoadObject::ValidLengthChanged() +{ + mObject->SetValidLength(mValidLength->text().toDouble()); +} + +void SettingsRoadObject::TypeChanged(const QString & text) +{ + mObject->SetType(text.toStdString()); + emit RoadGeometryChanged(true); +} + +void SettingsRoadObject::SubTypeChanged() +{ + mObject->SetSubType(mSubType->text().toStdString()); +} + +void SettingsRoadObject::HeadingChanged() +{ + mObject->SetHeading(mHeading->text().toDouble()); + emit RoadGeometryChanged(true); +} + +void SettingsRoadObject::BoundingBoxChanged(bool on) +{ + double length,width,height; + + if(on) + { + length=mBoxLength->text().toDouble(); + width=mBoxWidth->text().toDouble(); + height=mBoxHeight->text().toDouble(); + mObject->SetBoundingBox(length,width,height); + mBoundingCyl->setChecked(false); + } + else + { + mObject->ClearBounding(); + } + + emit RoadGeometryChanged(true); +} + +void SettingsRoadObject::BoxLengthChanged() +{ + double length,width,height; + + length=mBoxLength->text().toDouble(); + width=mBoxWidth->text().toDouble(); + height=mBoxHeight->text().toDouble(); + mObject->SetBoundingBox(length,width,height); + + emit RoadGeometryChanged(true); +} + +void SettingsRoadObject::BoxWidthChanged() +{ + double length,width,height; + + length=mBoxLength->text().toDouble(); + width=mBoxWidth->text().toDouble(); + height=mBoxHeight->text().toDouble(); + mObject->SetBoundingBox(length,width,height); + + emit RoadGeometryChanged(true); +} + +void SettingsRoadObject::BoxHeightChanged() +{ + double length,width,height; + + length=mBoxLength->text().toDouble(); + width=mBoxWidth->text().toDouble(); + height=mBoxHeight->text().toDouble(); + mObject->SetBoundingBox(length,width,height); + + emit RoadGeometryChanged(true); +} + +void SettingsRoadObject::BoundingCylChanged(bool on) +{ + double radius,height; + + if(on) + { + radius=mCylRadius->text().toDouble(); + height=mCylHeight->text().toDouble(); + mObject->SetBoundingCylinder(radius,height); + mBoundingBox->setChecked(false); + } + else + { + mObject->ClearBounding(); + } + + emit RoadGeometryChanged(true); +} + +void SettingsRoadObject::CylRadiusChanged() +{ + double radius,height; + + radius=mCylRadius->text().toDouble(); + height=mCylHeight->text().toDouble(); + mObject->SetBoundingCylinder(radius,height); + + emit RoadGeometryChanged(true); +} + +void SettingsRoadObject::CylHeightChanged() +{ + double radius,height; + + radius=mCylRadius->text().toDouble(); + height=mCylHeight->text().toDouble(); + mObject->SetBoundingCylinder(radius,height); + + emit RoadGeometryChanged(true); +} + + diff --git a/OpenRoadEd/Qt/SettingsWidgets/SettingsRoadObject.h b/OpenRoadEd/Qt/SettingsWidgets/SettingsRoadObject.h new file mode 100644 index 0000000000000000000000000000000000000000..5aa9a02daf1a81e1ed6c8e39a7665c2192002b5a --- /dev/null +++ b/OpenRoadEd/Qt/SettingsWidgets/SettingsRoadObject.h @@ -0,0 +1,102 @@ +#ifndef SETTINGSROADOBJECT_H +#define SETTINGSROADOBJECT_H + + +#include <QtGui/QWidget> +#include <QtGui/QtGui> + +#include "../../OpenDrive/OpenDrive.h" +#include "../../OpenDrive/ObjectSignal.h" + +#include "../ToolsDialogs/GetRoadDialog.h" + +#include <map> + +/** + * Class that holds all the properties for the ROAD record + * + */ +class SettingsRoadObject : public QWidget +{ + Q_OBJECT +public: + /** + * Initializes the properties panel and the UI elements + */ + SettingsRoadObject(OpenDrive *openDrive); + + /** + * Loads the data for a given record + * + * @param road Road record whose properties are to be loaded + */ + void LoadData(Object *object); +private: + /** + * OpenDrive reference for "Select Road" dialog + */ + OpenDrive *mOpenDrive; + /** + * Road whose properties are to be displayed + */ + Object *mObject; + + std::map<std::string,std::string> mTypeMap; + + /** + * Interface widgets + */ + QLineEdit *mName; + QLineEdit *mId; + QLineEdit *mS; + QLineEdit *mT; + QCheckBox *mDynamic; + QComboBox *mOrientation; + QLineEdit *mZOffset; + QLineEdit *mValidLength; + QComboBox *mType; + QLineEdit *mSubType; + QLineEdit *mHeading; + QGroupBox *mBoundingBox; + QLineEdit *mBoxLength; + QLineEdit *mBoxWidth; + QLineEdit *mBoxHeight; + QGroupBox *mBoundingCyl; + QLineEdit *mCylRadius; + QLineEdit *mCylHeight; + +public slots: + + /** + * Methods called when properties change + */ + void NameChanged(); + void IdChanged(); + void SChanged(); + void TChanged(); + void DynamicChanged(bool on); + void OrientationChanged(const QString & text); + void ZOffsetChanged(); + void ValidLengthChanged(); + void TypeChanged(const QString & text); + void SubTypeChanged(); + void HeadingChanged(); + void BoundingBoxChanged(bool on); + void BoxLengthChanged(); + void BoxWidthChanged(); + void BoxHeightChanged(); + void BoundingCylChanged(bool on); + void CylRadiusChanged(); + void CylHeightChanged(); + +signals: + /** + * Object emitted when critical road items are changed + * that require that the road to be redrawn + * + * @param recalculateRoad Set to true if geometry records have to be recalculated (usualy true for this record) + */ + void RoadGeometryChanged(bool recalculateRoad); +}; + +#endif diff --git a/OpenRoadEd/Qt/SettingsWidgets/SettingsRoadSignal.cpp b/OpenRoadEd/Qt/SettingsWidgets/SettingsRoadSignal.cpp index 2ba7186ae7efac9f71beb7f0257b0abd1c2eb783..6d9bc594c6f55093bd2cf3fc1c6014970fbca777 100644 --- a/OpenRoadEd/Qt/SettingsWidgets/SettingsRoadSignal.cpp +++ b/OpenRoadEd/Qt/SettingsWidgets/SettingsRoadSignal.cpp @@ -172,10 +172,18 @@ void SettingsRoadSignal::LoadData(Signal *signal) mType->setCurrentIndex(1); else if(signal->GetType()=="206") mType->setCurrentIndex(2); + else if(signal->GetType()=="314") + mType->setCurrentIndex(3); + else if(signal->GetType()=="308") + mType->setCurrentIndex(4); else if(signal->GetType()=="209") mType->setCurrentIndex(5); else if(signal->GetType()=="205") mType->setCurrentIndex(6); + else if(signal->GetType()=="350") + mType->setCurrentIndex(7); + else if(signal->GetType()=="215") + mType->setCurrentIndex(8); else if(signal->GetType()=="276") mType->setCurrentIndex(9); else if(signal->GetType()=="267")