54std::map<std::string, osg::ref_ptr<osg::Node> > GUIOSGBuilder::myCars;
61GUIOSGBuilder::buildOSGScene(osg::Node*
const tlg, osg::Node*
const tly, osg::Node*
const tlr, osg::Node*
const tlu, osg::Node*
const pole) {
62 osgUtil::Tessellator tesselator;
63 osg::Group* root =
new osg::Group();
66 for (
const MSEdge* e : net->getEdgeControl().getEdges()) {
67 if (!e->isInternal()) {
68 buildOSGEdgeGeometry(*e, *root, tesselator);
78 for (std::vector<std::string>::const_iterator i = tlids.begin(); i != tlids.end(); ++i) {
80 buildTrafficLightDetails(vars, tlg, tly, tlr, tlu, pole, *root);
83 const MSLane* lastLane = 0;
85 for (MSTrafficLightLogic::LaneVectorVector::const_iterator j = lanes.begin(); j != lanes.end(); ++j, ++idx) {
86 if ((*j).size() == 0) {
89 const MSLane*
const lane = (*j)[0];
93 if (lane == lastLane) {
97 d.
centerX = pos.
x() - 1.5 * sin(angle);
98 d.
centerY = pos.
y() - 1.5 * cos(angle);
100 osg::PositionAttitudeTransform* tlNode = getTrafficLight(d, vars, vars.
getActive()->
getLinksAt(idx)[0],
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
false, .25, -1, 1.);
101 tlNode->setName(
"tlLogic:" + *i);
102 root->addChild(tlNode);
108 for (
const auto& entry : net->getShapeContainer().getPolygons()) {
109 buildPolygonGeometry(*entry.second, *root, tesselator);
111 for (
const auto& entry : net->getShapeContainer().getPOIs()) {
112 buildPoIGeometry(*entry.second, *root, tesselator);
121 osg::Light* light =
new osg::Light(d.
filename[5] -
'0');
123 light->setPosition(osg::Vec4(0.0, 0.0, 0.0, 1.0));
124 light->setDiffuse(osg::Vec4(1.0, 1.0, 1.0, 1.0));
125 light->setSpecular(osg::Vec4(1.0, 1.0, 1.0, 1.0));
126 light->setAmbient(osg::Vec4(1.0, 1.0, 1.0, 1.0));
128 osg::LightSource* lightSource =
new osg::LightSource();
129 lightSource->setLight(light);
130 lightSource->setLocalStateSetModes(osg::StateAttribute::ON);
131 lightSource->setStateSetModes(*addTo.getOrCreateStateSet(), osg::StateAttribute::ON);
133 osg::PositionAttitudeTransform* lightTransform =
new osg::PositionAttitudeTransform();
134 lightTransform->addChild(lightSource);
136 lightTransform->setScale(osg::Vec3d(0.1, 0.1, 0.1));
137 addTo.addChild(lightTransform);
142GUIOSGBuilder::buildOSGEdgeGeometry(
const MSEdge& edge,
144 osgUtil::Tessellator& tessellator) {
145 const std::vector<MSLane*>& lanes = edge.
getLanes();
146 for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
151 const int originalSize = (int)shape.size();
152 osg::Geode* geode =
new osg::Geode();
153 osg::Geometry* geom =
new osg::Geometry();
154 geode->addDrawable(geom);
155 geode->setName(
"lane:" + l->
getID());
156 addTo.addChild(geode);
158 const int upperShapeSize = originalSize * geomFactor;
159 const int totalShapeSize = (extrude) ? originalSize * 2 * geomFactor : originalSize * geomFactor;
160 const float zOffset = (extrude) ? (edge.
isCrossing()) ? 0.01f : 0.1f : 0.f;
161 osg::Vec4ubArray* osg_colors =
new osg::Vec4ubArray(1);
162 (*osg_colors)[0].set(128, 128, 128, 255);
163 geom->setColorArray(osg_colors, osg::Array::BIND_OVERALL);
164 osg::Vec3Array* osg_coords =
new osg::Vec3Array(totalShapeSize);
165 geom->setVertexArray(osg_coords);
168 int index = upperShapeSize - 1;
169 for (
int k = 0; k < upperShapeSize; ++k, --index) {
170 (*osg_coords)[index].set((
float)shape[k].x(), (
float)shape[k].y(), (
float)shape[k].z() + zOffset);
172 geom->addPrimitiveSet(
new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, upperShapeSize));
177 for (
int k = (
int)rshape.size() - 1; k >= 0; --k, ++index) {
178 (*osg_coords)[index].set((
float)rshape[k].x(), (float)rshape[k].y(), (float)rshape[k].z() + zOffset);
182 for (
int k = 0; k < (int)lshape.size(); ++k, ++index) {
183 (*osg_coords)[index].set((
float)lshape[k].x(), (float)lshape[k].y(), (float)lshape[k].z() + zOffset);
185 sizeDiff = (int)rshape.size() + (int)lshape.size() - upperShapeSize;
186 int minSize =
MIN2((
int)rshape.size(), (
int)lshape.size());
187 osg::DrawElementsUInt* surface =
new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP, 0);
188 for (
int i = 0; i < minSize; ++i) {
189 surface->push_back(i);
190 surface->push_back(upperShapeSize + sizeDiff - 1 - i);
192 geom->addPrimitiveSet(surface);
195 int index = upperShapeSize;
196 for (
int k = 0; k < upperShapeSize + sizeDiff; ++k, ++index) {
197 (*osg_coords)[index].set((*osg_coords)[k].x(), (*osg_coords)[k].y(), (*osg_coords)[k].z() - zOffset);
200 for (
int i = 0; i < upperShapeSize + sizeDiff; ++i) {
201 osg::Vec3 surfaceVec = (*osg_coords)[i] - (*osg_coords)[(i + 1) % (upperShapeSize + sizeDiff)];
202 if (surfaceVec.length() > 0.) {
203 osg::DrawElementsUInt* kerb =
new osg::DrawElementsUInt(osg::PrimitiveSet::POLYGON, 0);
205 kerb->push_back(upperShapeSize + i);
206 kerb->push_back(upperShapeSize + (i + 1) % (upperShapeSize + sizeDiff));
207 kerb->push_back((i + 1) % (upperShapeSize + sizeDiff));
208 geom->addPrimitiveSet(kerb);
213 osg::ref_ptr<osg::StateSet> ss = geode->getOrCreateStateSet();
214 ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
215 ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
217 if (shape.size() > 2) {
218 tessellator.retessellatePolygons(*geom);
221 std::cout <<
"l=" << l->
getID() <<
" origPoints=" << shape.size() <<
" geomSize=" << geom->getVertexArray()->getNumElements() <<
" points=";
222 for (
int i = 0; i < (int)geom->getVertexArray()->getNumElements(); i++) {
223 const osg::Vec3& p = (*((osg::Vec3Array*)geom->getVertexArray()))[i];
224 std::cout << p.x() <<
"," << p.y() <<
"," << p.z() <<
" ";
229 osgUtil::SmoothingVisitor sv;
230#if OSG_MIN_VERSION_REQUIRED(3,5,4)
231 sv.setCreaseAngle(0.6 * osg::PI);
234 static_cast<GUILane*
>(l)->setGeometry(geom);
242 osgUtil::Tessellator& tessellator) {
244 osg::Geode* geode =
new osg::Geode();
245 osg::Geometry* geom =
new osg::Geometry();
246 geode->addDrawable(geom);
248 addTo.addChild(geode);
249 dynamic_cast<GUIGlObject&
>(junction).setNode(geode);
250 osg::Vec3Array* osg_coords =
new osg::Vec3Array((
int)shape.size());
251 geom->setVertexArray(osg_coords);
252 for (
int k = 0; k < (int)shape.size(); ++k) {
253 (*osg_coords)[k].set((
float)shape[k].x(), (float)shape[k].y(), (float)shape[k].z());
255 osg::Vec3Array* osg_normals =
new osg::Vec3Array(1);
256 (*osg_normals)[0] = osg::Vec3(0, 0, 1);
257 geom->setNormalArray(osg_normals, osg::Array::BIND_PER_PRIMITIVE_SET);
258 osg::Vec4ubArray* osg_colors =
new osg::Vec4ubArray(1);
259 (*osg_colors)[0].set(128, 128, 128, 255);
260 geom->setColorArray(osg_colors, osg::Array::BIND_OVERALL);
261 geom->addPrimitiveSet(
new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, (
int)shape.size()));
263 osg::ref_ptr<osg::StateSet> ss = geode->getOrCreateStateSet();
264 ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
265 ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
267 if (shape.size() > 4) {
268 tessellator.retessellatePolygons(*geom);
270 junction.setGeometry(geom);
275GUIOSGBuilder::buildPolygonGeometry(
const SUMOPolygon& poly, osg::Group& addTo, osgUtil::Tessellator& tessellator) {
277 const std::vector<PositionVector>& holes = poly.
getHoles();
282 osg::Geode* geode =
new osg::Geode();
283 osg::Geometry* geom =
new osg::Geometry();
284 geode->addDrawable(geom);
285 geode->setName(
"polygon:" + poly.
getID());
286 addTo.addChild(geode);
287 osg::Vec3Array* osg_coords =
new osg::Vec3Array((
int)shape.size());
288 geom->setVertexArray(osg_coords);
289 for (
int k = 0; k < (int)shape.size(); ++k) {
290 (*osg_coords)[k].set((
float)shape[k].x(), (float)shape[k].y(), (useZ)? (
float)shape[k].z() : 0.1f);
293 if (holes.size() > 0) {
296 osg::Vec3Array* osg_normals =
new osg::Vec3Array(1);
297 (*osg_normals)[0] = osg::Vec3(0, 0, 1);
298 geom->setNormalArray(osg_normals, osg::Array::BIND_PER_PRIMITIVE_SET);
299 osg::Vec4ubArray* osg_colors =
new osg::Vec4ubArray(1);
302 geom->setColorArray(osg_colors, osg::Array::BIND_OVERALL);
303 geom->addPrimitiveSet(
new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, (
int)shape.size()));
305 osg::ref_ptr<osg::StateSet> ss = geode->getOrCreateStateSet();
306 ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
307 ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
309 if (shape.size() > 4) {
310 tessellator.retessellatePolygons(*geom);
316GUIOSGBuilder::buildPoIGeometry(
const PointOfInterest& poi, osg::Group& addTo, osgUtil::Tessellator& tessellator) {
317 osg::Geode* geode =
new osg::Geode();
318 osg::Geometry* geom =
new osg::Geometry();
319 geode->addDrawable(geom);
320 geode->setName(
"poi:" + poi.
getID());
321 addTo.addChild(geode);
322 osg::Vec3Array* osg_coords =
new osg::Vec3Array(4);
323 geom->setVertexArray(osg_coords);
326 const double width = poi.
getWidth();
329 shape.push_back(
Position(center.
x() - 0.5 * width, center.
y() + 0.5 * height));
330 shape.push_back(
Position(center.
x() + 0.5 * width, center.
y() + 0.5 * height));
331 shape.push_back(
Position(center.
x() + 0.5 * width, center.
y() - 0.5 * height));
332 shape.push_back(
Position(center.
x() - 0.5 * width, center.
y() - 0.5 * height));
333 for (
unsigned int k = 0; k < shape.size(); ++k) {
334 (*osg_coords)[k].set((
float)shape[k].x(), (
float)shape[k].y(), 0.2f);
336 osg::Vec3Array* osg_normals =
new osg::Vec3Array(1);
337 (*osg_normals)[0] = osg::Vec3(0, 0, 1);
338 geom->setNormalArray(osg_normals, osg::Array::BIND_PER_PRIMITIVE_SET);
339 osg::Vec4ubArray* osg_colors =
new osg::Vec4ubArray(1);
342 geom->setColorArray(osg_colors, osg::Array::BIND_OVERALL);
343 geom->addPrimitiveSet(
new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, (
int)shape.size()));
345 osg::ref_ptr<osg::StateSet> ss = geode->getOrCreateStateSet();
346 ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
347 ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
349 if (shape.size() > 4) {
350 tessellator.retessellatePolygons(*geom);
356GUIOSGBuilder::buildTrafficLightDetails(
MSTLLogicControl::TLSLogicVariants& vars, osg::Node*
const tlg, osg::Node*
const tly, osg::Node*
const tlr, osg::Node*
const tlu, osg::Node* poleBase, osg::Group& addTo) {
358 osg::ComputeBoundsVisitor bboxCalc;
359 poleBase->accept(bboxCalc);
360 const double poleDiameter = bboxCalc.getBoundingBox().yMax() - bboxCalc.getBoundingBox().yMin();
361 tlg->accept(bboxCalc);
362 const double tlWidth = bboxCalc.getBoundingBox().yMax() - bboxCalc.getBoundingBox().yMin();
367 std::set<const MSEdge*> seenEdges;
370 for (
const MSLink* tlLink : lv) {
372 const MSEdge* approach = &tlLink->getLaneBefore()->getEdge();
373 if (!approach->
isWalkingArea() && seenEdges.find(approach) != seenEdges.end()) {
376 const std::vector<MSLane*> appLanes = approach->
getLanes();
378 const double poleMinHeight = 5.;
379 const double poleOffset = .5;
380 double angle = 90. - appLanes[0]->getShape().rotationDegreeAtOffset(-1.);
382 Position pos = appLanes[0]->getShape().back();
383 double skipWidth = 0.;
384 int firstSignalLaneIx = 0;
385 std::vector<std::pair<osg::Group*, osg::Vec3d>> repeaters;
387 osg::PositionAttitudeTransform* appBase =
new osg::PositionAttitudeTransform();
388 osg::PositionAttitudeTransform* rightPoleBase =
new osg::PositionAttitudeTransform();
389 osg::PositionAttitudeTransform* rightPoleScaleNode =
new osg::PositionAttitudeTransform();
390 rightPoleScaleNode->addChild(poleBase);
391 rightPoleBase->addChild(rightPoleScaleNode);
392 appBase->addChild(rightPoleBase);
393 rightPoleBase->setPosition(osg::Vec3d(pos.
x(), pos.
y(), pos.
z()));
394 rightPoleBase->setAttitude(osg::Quat(0., osg::Vec3d(1, 0, 0),
395 0., osg::Vec3d(0, 1, 0),
396 DEG2RAD(angle), osg::Vec3d(0, 0, 1)));
398 rightPoleScaleNode->setScale(osg::Vec3d(.12 / poleDiameter, .12 / poleDiameter, 2.8));
402 appBase->setPosition(appBase->getPosition() + offset * (poleOffset + approach->
getLength()));
403 appBase->setAttitude(osg::Quat(0., osg::Vec3d(1, 0, 0),
404 0., osg::Vec3d(0, 1, 0),
405 DEG2RAD(angle + 180), osg::Vec3d(0, 0, 1)));
407 pos = tlLink->getLane()->getShape().back();
408 angle = 90. - tlLink->getLane()->getShape().rotationDegreeAtOffset(-1.);
409 rightPoleBase->setPosition(osg::Vec3d(pos.
x(), pos.
y(), pos.
z()) - osg::Vec3d(poleOffset * cos(
DEG2RAD(angle)), poleOffset * sin(
DEG2RAD(angle)), 0.));
410 rightPoleBase->setAttitude(osg::Quat(0., osg::Vec3d(1, 0, 0),
411 0., osg::Vec3d(0, 1, 0),
412 DEG2RAD(angle), osg::Vec3d(0, 0, 1)));
413 if (tlLink->getLane()->getLinkCont()[0]->getTLIndex() < 0) {
414 osg::PositionAttitudeTransform* leftPoleBase =
new osg::PositionAttitudeTransform();
415 osg::PositionAttitudeTransform* leftPoleScaleNode =
new osg::PositionAttitudeTransform();
416 appBase->addChild(leftPoleBase);
417 leftPoleScaleNode->addChild(poleBase);
418 leftPoleScaleNode->setScale(osg::Vec3d(.12 / poleDiameter, .12 / poleDiameter, 2.8));
419 leftPoleBase->addChild(leftPoleScaleNode);
420 double otherAngle = 90. - tlLink->getLane()->getShape().rotationDegreeAtOffset(1.);
421 Position otherPosRel = tlLink->getLane()->getShape().front();
422 osg::Vec3d leftPolePos(otherPosRel.
x(), otherPosRel.
y(), otherPosRel.
z());
423 leftPoleBase->setPosition(leftPolePos + osg::Vec3d(poleOffset * cos(
DEG2RAD(otherAngle)), poleOffset * sin(
DEG2RAD(otherAngle)), 0.));
424 leftPoleBase->setAttitude(osg::Quat(0., osg::Vec3d(1., 0., 0.),
425 0., osg::Vec3d(0., 1., 0.),
426 DEG2RAD(angle + 180.), osg::Vec3d(0., 0., 1.)));
427 repeaters.push_back({ leftPoleBase, osg::Vec3d(0., 0., leftPoleBase->getPosition().z())});
430 double laneWidth = appLanes[0]->getWidth();
431 osg::Vec3d offset(-poleOffset * cos(
DEG2RAD(angle)) - (.5 * laneWidth - skipWidth + poleOffset) * sin(
DEG2RAD(angle)), poleOffset * sin(
DEG2RAD(angle)) + (.5 * laneWidth - skipWidth + poleOffset) * cos(
DEG2RAD(angle)), 0.);
432 rightPoleBase->setPosition(rightPoleBase->getPosition() + offset);
436 if (!
noVehicles(appLanes.back()->getPermissions())) {
437 for (
MSLane* appLane : appLanes) {
440 skipWidth += appLane->getWidth();
447 const double laneWidth = appLanes[0]->getWidth();
448 const double horizontalWidth = approach->
getWidth() - skipWidth;
449 const int laneCount = (int)appLanes.size() - firstSignalLaneIx;
450 osg::Vec3d offset(-poleOffset * cos(
DEG2RAD(angle)) - (.5 * laneWidth - skipWidth + poleOffset) * sin(
DEG2RAD(angle)), -poleOffset * sin(
DEG2RAD(angle)) + (.5 * laneWidth - skipWidth + poleOffset) * cos(
DEG2RAD(angle)), 0.);
451 rightPoleBase->setPosition(rightPoleBase->getPosition() + offset);
454 const double cantiWidth = horizontalWidth - .1 * appLanes.back()->getWidth() + poleOffset;
455 const double holderWidth = cantiWidth - .4 * appLanes.back()->getWidth();
456 const double holderAngle = 7.5;
457 const double extraHeight = sin(
DEG2RAD(holderAngle)) * holderWidth;
458 rightPoleScaleNode->setScale(osg::Vec3d(.25 / poleDiameter, .25 / poleDiameter, poleMinHeight + extraHeight));
459 osg::PositionAttitudeTransform* cantileverBase =
new osg::PositionAttitudeTransform();
460 cantileverBase->setPosition(osg::Vec3d(0., 0., poleMinHeight));
461 cantileverBase->setAttitude(osg::Quat(
DEG2RAD(90.), osg::Vec3d(1, 0, 0),
462 0., osg::Vec3d(0, 1, 0),
463 0., osg::Vec3d(0, 0, 1)));
464 cantileverBase->setScale(osg::Vec3d(1., 1., cantiWidth));
465 cantileverBase->addChild(poleBase);
466 rightPoleBase->addChild(cantileverBase);
467 osg::PositionAttitudeTransform* cantileverHolderBase =
new osg::PositionAttitudeTransform();
468 cantileverHolderBase->setPosition(osg::Vec3d(0., 0., poleMinHeight + extraHeight - .02));
469 cantileverHolderBase->setAttitude(osg::Quat(
DEG2RAD(90. + holderAngle), osg::Vec3d(1, 0, 0),
470 0., osg::Vec3d(0, 1, 0),
471 0., osg::Vec3d(0, 0, 1)));
472 cantileverHolderBase->setScale(osg::Vec3d(.04 / poleDiameter, .04 / poleDiameter, sqrt(pow(holderWidth, 2.) + pow(extraHeight, 2.))));
473 cantileverHolderBase->addChild(poleBase);
474 rightPoleBase->addChild(cantileverHolderBase);
476 rightPoleScaleNode->setScale(osg::Vec3d(.25 / poleDiameter, .25 / poleDiameter, poleMinHeight));
477 osg::PositionAttitudeTransform* leftPoleBase =
new osg::PositionAttitudeTransform();
478 leftPoleBase->addChild(poleBase);
479 leftPoleBase->setScale(osg::Vec3d(.25 / poleDiameter, .25 / poleDiameter, poleMinHeight));
480 osg::Vec3d leftPolePos = osg::Vec3d(0, -(horizontalWidth + 2. * poleOffset), 0.);
481 leftPoleBase->setPosition(leftPolePos);
482 rightPoleBase->addChild(leftPoleBase);
483 osg::PositionAttitudeTransform* bridgeBase =
new osg::PositionAttitudeTransform();
484 bridgeBase->setPosition(osg::Vec3d(0., 0., poleMinHeight - .125));
485 bridgeBase->setAttitude(osg::Quat(
DEG2RAD(90.), osg::Vec3d(1, 0, 0),
486 0., osg::Vec3d(0, 1, 0),
487 0., osg::Vec3d(0, 0, 1)));
488 bridgeBase->setScale(osg::Vec3d(.25 / poleDiameter, .25 / poleDiameter, leftPolePos.length()));
489 bridgeBase->addChild(poleBase);
490 rightPoleBase->addChild(bridgeBase);
493 seenEdges.insert(approach);
496 double refPos = poleOffset ;
497 std::vector<MSLane*>::const_iterator it = appLanes.begin();
498 for (std::advance(it, firstSignalLaneIx); it != appLanes.end(); it++) {
500 const std::vector<MSLink*>& links = (*it)->getLinkCont();
501 std::set<int> tlIndices;
502 for (
MSLink* link : links) {
503 if (link->getTLIndex() > -1) {
504 tlIndices.insert(link->getTLIndex());
507 std::set<int> seenTlIndices;
508 bool placeRepeaters =
true;
509 for (
MSLink* link : links) {
510 std::vector<std::pair<osg::Group*, osg::Vec3d>> signalTransforms = { {rightPoleBase, osg::Vec3d(0., 0., 0.)} };
511 if (placeRepeaters) {
512 signalTransforms.insert(signalTransforms.end(), repeaters.begin(), repeaters.end());
514 placeRepeaters =
false;
516 int tlIndex = link->getTLIndex();
517 if (tlIndex < 0 || seenTlIndices.find(tlIndex) != seenTlIndices.end()) {
520 for (
const std::pair<osg::Group*, osg::Vec3d>& transform : signalTransforms) {
522 d.
centerX = transform.second.x() + 0.15;
523 d.
centerY = (onlyPedCycle) ? 0. : -(refPos + .5 * (*it)->getWidth() - ((double)tlIndices.size() / 2. - 1. + (double)seenTlIndices.size()) * 1.5 * tlWidth);
524 d.
centerY += transform.second.y();
525 d.
centerZ = (onlyPedCycle) ? 2.2 : 3.8;
526 d.
centerZ += transform.second.z();
527 d.
altitude = (onlyPedCycle) ? 0.6 : -1;
528 osg::PositionAttitudeTransform* tlNode = getTrafficLight(d, vars, links[0], tlg, tly, tlr, tlu, poleBase,
false);
529 tlNode->setAttitude(osg::Quat(0., osg::Vec3d(1, 0, 0),
530 0., osg::Vec3d(0, 1, 0),
531 DEG2RAD(180.0), osg::Vec3d(0, 0, 1)));
532 transform.first->addChild(tlNode);
534 seenTlIndices.insert(tlIndex);
540 refPos += (*it)->getWidth();
543 appBase->setNodeMask(GUIOSGView::NODESET_TLSMODELS);
544 appBase->setName(
"tlLogic:" + tlLogic->
getID());
545 addTo.addChild(appBase);
553 osg::Node* pLoadedModel = osgDB::readNodeFile(d.
filename);
554 osg::PositionAttitudeTransform* base =
new osg::PositionAttitudeTransform();
556 if (pLoadedModel ==
nullptr) {
558 osg::Image* pImage = osgDB::readImageFile(d.
filename);
559 if (pImage ==
nullptr) {
564 osg::Texture2D* texture =
new osg::Texture2D();
565 texture->setImage(pImage);
566 osg::Geometry* quad = osg::createTexturedQuadGeometry(osg::Vec3d(-0.5 * d.
width, -0.5 * d.
height, 0.), osg::Vec3d(d.
width, 0., 0.), osg::Vec3d(0., d.
height, 0.));
567 quad->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture);
568 osg::Geode*
const pModel =
new osg::Geode();
569 pModel->addDrawable(quad);
570 base->addChild(pModel);
573 osg::ShadeModel* sm =
new osg::ShadeModel();
574 sm->setMode(osg::ShadeModel::FLAT);
575 pLoadedModel->getOrCreateStateSet()->setAttribute(sm);
576 base->addChild(pLoadedModel);
578 osg::ComputeBoundsVisitor bboxCalc;
579 base->accept(bboxCalc);
580 const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
582 double xScale = d.
width > 0 ? d.
width / (bbox.xMax() - bbox.xMin()) : 1.;
583 double yScale = d.
height > 0 ? d.
height / (bbox.yMax() - bbox.yMin()) : 1.;
584 const double zScale = d.
altitude > 0 ? d.
altitude / (bbox.zMax() - bbox.zMin()) : 1.;
586 xScale = yScale = zScale;
588 base->setScale(osg::Vec3d(xScale, yScale, zScale));
590 base->setAttitude(osg::Quat(osg::DegreesToRadians(d.
roll), osg::Vec3d(1, 0, 0),
591 osg::DegreesToRadians(d.
tilt), osg::Vec3d(0, 1, 0),
592 osg::DegreesToRadians(d.
rot), osg::Vec3d(0, 0, 1)));
593 addTo.addChild(base);
597osg::PositionAttitudeTransform*
598GUIOSGBuilder::getTrafficLight(
const GUISUMOAbstractView::Decal& d,
MSTLLogicControl::TLSLogicVariants& vars,
const MSLink* link, osg::Node*
const tlg, osg::Node*
const tly, osg::Node*
const tlr, osg::Node*
const tlu, osg::Node*
const pole,
const bool withPole,
const double size,
double poleHeight,
double transparency) {
599 osg::PositionAttitudeTransform* ret =
new osg::PositionAttitudeTransform();
600 double xScale = 1., yScale = 1., zScale = 1.;
601 if (tlg !=
nullptr) {
602 osg::ComputeBoundsVisitor bboxCalc;
603 tlg->accept(bboxCalc);
604 const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
605 xScale = d.
width > 0 ? d.
width / (bbox.xMax() - bbox.xMin()) : 1.;
606 yScale = d.
height > 0 ? d.
height / (bbox.yMax() - bbox.yMin()) : 1.;
607 double addHeight = (withPole) ? poleHeight : 0.;
608 zScale = d.
altitude > 0 ? d.
altitude / (addHeight + bbox.zMax() - bbox.zMin()) : 1.;
611 xScale = yScale = zScale;
613 osg::PositionAttitudeTransform* base =
new osg::PositionAttitudeTransform();
614 osg::Switch* switchNode =
new osg::Switch();
615 switchNode->addChild(createTrafficLightState(d, tlg, withPole, size, osg::Vec4d(0., 1., 0., transparency)));
616 switchNode->addChild(createTrafficLightState(d, tly, withPole, size, osg::Vec4d(1., 1., 0., transparency)));
617 switchNode->addChild(createTrafficLightState(d, tlr, withPole, size, osg::Vec4d(1., 0., 0., transparency)));
618 switchNode->addChild(createTrafficLightState(d, tlu, withPole, size, osg::Vec4d(1., .5, 0., transparency)));
619 base->addChild(switchNode);
622 base->setPosition(osg::Vec3d(0., 0., poleHeight));
623 osg::PositionAttitudeTransform* poleBase =
new osg::PositionAttitudeTransform();
624 poleBase->addChild(pole);
625 poleBase->setScale(osg::Vec3d(1., 1., poleHeight));
626 ret->addChild(poleBase);
628 ret->setAttitude(osg::Quat(osg::DegreesToRadians(d.
roll), osg::Vec3(1, 0, 0),
629 osg::DegreesToRadians(d.
tilt), osg::Vec3(0, 1, 0),
630 osg::DegreesToRadians(d.
rot), osg::Vec3(0, 0, 1)));
632 ret->setScale(osg::Vec3d(xScale, yScale, zScale));
638osg::PositionAttitudeTransform*
639GUIOSGBuilder::createTrafficLightState(
const GUISUMOAbstractView::Decal& d, osg::Node* tl,
const double withPole,
const double size, osg::Vec4d color) {
640 osg::PositionAttitudeTransform* ret =
new osg::PositionAttitudeTransform();
645 unsigned int nodeMask = (withPole) ? GUIOSGView::NodeSetGroup::NODESET_TLSDOMES : GUIOSGView::NodeSetGroup::NODESET_TLSLINKMARKERS;
646 osg::Geode* geode =
new osg::Geode();
647 osg::Vec3d center = osg::Vec3d(0., 0., (withPole) ? -1.8 : 0.);
648 osg::ShapeDrawable* shape =
new osg::ShapeDrawable(
new osg::Sphere(center, (
float)size));
649 geode->addDrawable(shape);
650 osg::ref_ptr<osg::StateSet> ss = shape->getOrCreateStateSet();
651 ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
652 ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
653 shape->setColor(color);
654 osg::PositionAttitudeTransform* ellipse =
new osg::PositionAttitudeTransform();
655 ellipse->addChild(geode);
656 ellipse->setPosition(center);
657 ellipse->setPivotPoint(center);
659 ellipse->setScale(osg::Vec3d(4., 4., 2.5 * d.
altitude + 1.1));
661 ellipse->setScale(osg::Vec3d(4., 4., 1.1));
663 ellipse->setNodeMask(nodeMask);
664 ret->addChild(ellipse);
671GUIOSGBuilder::setShapeState(osg::ref_ptr<osg::ShapeDrawable> shape) {
672 osg::ref_ptr<osg::StateSet> ss = shape->getOrCreateStateSet();
673 ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
674 ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
678GUIOSGView::OSGMovable
680 GUIOSGView::OSGMovable m;
681 m.pos =
new osg::PositionAttitudeTransform();
682 double enlarge = 0.05;
683 const std::string& osgFile = type.
getOSGFile();
684 if (myCars.find(osgFile) == myCars.end()) {
685 myCars[osgFile] = osgDB::readNodeFile(osgFile);
686 if (myCars[osgFile] == 0) {
687 WRITE_ERRORF(
TL(
"Could not load '%'. The model is replaced by a cone shape."), osgFile);
688 osg::PositionAttitudeTransform* rot =
new osg::PositionAttitudeTransform();
689 rot->addChild(
new osg::ShapeDrawable(
new osg::Cone(osg::Vec3d(0, 0, 0), 1.0f, 1.0f)));
690 rot->setAttitude(osg::Quat(osg::DegreesToRadians(90.), osg::Vec3(1, 0, 0),
691 0., osg::Vec3(0, 1, 0),
692 0., osg::Vec3(0, 0, 1)));
693 myCars[osgFile] = rot;
696 osg::Node* carNode = myCars[osgFile];
697 if (carNode !=
nullptr) {
698 osg::ComputeBoundsVisitor bboxCalc;
699 carNode->accept(bboxCalc);
700 const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
701 osg::PositionAttitudeTransform* base =
new osg::PositionAttitudeTransform();
702 base->addChild(carNode);
703 base->setPivotPoint(osg::Vec3d((bbox.xMin() + bbox.xMax()) / 2., bbox.yMin(), bbox.zMin()));
704 base->setScale(osg::Vec3d(type.
getWidth() / (bbox.xMax() - bbox.xMin()),
705 type.
getLength() / (bbox.yMax() - bbox.yMin()),
706 type.
getHeight() / (bbox.zMax() - bbox.zMin())));
708 m.pos->addChild(base);
711 m.mat =
new osg::Material();
712 osg::ref_ptr<osg::StateSet> ss = base->getOrCreateStateSet();
713 ss->setAttribute(m.mat, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED);
714 ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
715 ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
718 m.lights =
new osg::Switch();
719 for (
double sideFactor = -1.; sideFactor < 2.5; sideFactor += 2.) {
720 osg::Geode* geode =
new osg::Geode();
721 osg::ShapeDrawable* right =
new osg::ShapeDrawable(
new osg::Sphere(osg::Vec3d((type.
getWidth() / 2. + enlarge)*sideFactor, 0., type.
getHeight() / 2.), 0.2f));
722 geode->addDrawable(right);
724 setShapeState(right);
725 right->setColor(osg::Vec4(1.f, .5f, 0.f, .8f));
726 osg::Sequence* seq =
new osg::Sequence();
728 seq->addChild(geode, .33);
729 seq->addChild(
new osg::Geode(), .33);
731 seq->setInterval(osg::Sequence::LOOP, 0, -1);
733 seq->setDuration(1.0f, -1);
735 seq->setMode(osg::Sequence::START);
736 m.lights->addChild(seq);
738 osg::Geode* geode =
new osg::Geode();
739 osg::CompositeShape* comp =
new osg::CompositeShape();
740 comp->addChild(
new osg::Sphere(osg::Vec3d(-(type.
getWidth() / 2. + enlarge), type.
getLength() + enlarge, type.
getHeight() / 2.), .2f));
741 comp->addChild(
new osg::Sphere(osg::Vec3d(type.
getWidth() / 2. + enlarge, type.
getLength() + enlarge, type.
getHeight() / 2.), .2f));
742 osg::ShapeDrawable* brake =
new osg::ShapeDrawable(comp);
743 brake->setColor(osg::Vec4(1.f, 0.f, 0.f, .8f));
744 geode->addDrawable(brake);
745 setShapeState(brake);
746 m.lights->addChild(geode);
748 osg::Vec3d center(0, -type.
getLength() / 2., 0.);
749 osg::PositionAttitudeTransform* ellipse =
new osg::PositionAttitudeTransform();
750 ellipse->addChild(geode);
751 ellipse->addChild(m.lights);
752 ellipse->setPivotPoint(center);
753 ellipse->setPosition(center);
754 m.pos->addChild(ellipse);
762GUIOSGBuilder::buildPlane(
const float length) {
763 osg::Geode* geode =
new osg::Geode();
764 osg::Geometry* geom =
new osg::Geometry;
765 geode->addDrawable(geom);
766 osg::Vec3Array* coords =
new osg::Vec3Array(4);
767 geom->setVertexArray(coords);
768 (*coords)[0].set(.5f * length, .5f * length, -0.1f);
769 (*coords)[1].set(.5f * length, -.5f * length, -0.1f);
770 (*coords)[2].set(-.5f * length, -.5f * length, -0.1f);
771 (*coords)[3].set(-.5f * length, .5f * length, -0.1f);
772 osg::Vec3Array* normals =
new osg::Vec3Array(1);
773 (*normals)[0].set(0, 0, 1);
774 geom->setNormalArray(normals, osg::Array::BIND_PER_PRIMITIVE_SET);
775 osg::Vec4ubArray* colors =
new osg::Vec4ubArray(1);
776 (*colors)[0].set(0, 255, 0, 255);
777 geom->setColorArray(colors, osg::Array::BIND_OVERALL);
778 geom->addPrimitiveSet(
new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, 4));
780 osg::ref_ptr<osg::StateSet> ss = geode->getOrCreateStateSet();
781 ss->setRenderingHint(osg::StateSet::OPAQUE_BIN);
782 ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
#define WRITE_MESSAGEF(...)
#define WRITE_ERRORF(...)
bool isForbidden(SVCPermissions permissions)
Returns whether an edge with the given permissions is a forbidden edge.
bool isSidewalk(SVCPermissions permissions)
Returns whether an edge with the given permissions is a sidewalk.
bool noVehicles(SVCPermissions permissions)
Returns whether an edge with the given permissions forbids vehicles.
bool isBikepath(SVCPermissions permissions)
Returns whether an edge with the given permissions is a bicycle edge.
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SVC_PEDESTRIAN
pedestrian
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
const MSJunction & getJunction() const
Returns the represented junction.
Representation of a lane in the micro simulation (gui-version)
A MSNet extended by some values for usage within the gui.
std::vector< GUIJunctionWrapper * > myJunctionWrapper
Wrapped MS-junctions.
A road/street connecting two junctions.
bool isCrossing() const
return whether this edge is a pedestrian crossing
SVCPermissions getPermissions() const
Returns the combined permissions of all lanes of this edge.
bool isWalkingArea() const
return whether this edge is walking area
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
double getLength() const
return the length of the edge
double getWidth() const
Returns the edges's width (sum over all lanes)
const PositionVector & getShape() const
Returns this junction's shape.
Representation of a lane in the micro simulation.
SVCPermissions getPermissions() const
Returns the vehicle class permissions for this lane.
virtual const PositionVector & getShape(bool) const
double getWidth() const
Returns the lane's width.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
MSTLLogicControl & getTLSControl()
Returns the tls logics control.
Storage for all programs of a single tls.
void addSwitchCommand(OnSwitchAction *c)
MSTrafficLightLogic * getActive() const
std::vector< std::string > getAllTLIds() const
TLSLogicVariants & get(const std::string &id) const
Returns the variants of a named tls.
The parent class for traffic light logics.
const LinkVectorVector & getLinks() const
Returns the list of lists of all affected links.
std::vector< LaneVector > LaneVectorVector
Definition of a list that holds lists of lanes that do have the same attribute.
const LaneVectorVector & getLaneVectors() const
Returns the list of lists of all lanes controlled by this tls.
const LinkVector & getLinksAt(int i) const
Returns the list of links that are controlled by the signals at the given position.
std::vector< LinkVector > LinkVectorVector
Definition of a list that holds lists of links that do have the same attribute.
std::vector< MSLink * > LinkVector
Definition of the list of links that are subjected to this tls.
The car-following model and parameter.
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
std::string getOSGFile() const
Get this vehicle type's 3D model file name.
double getHeight() const
Get the height which vehicles of this class shall have when being drawn.
double getLength() const
Get vehicle's length [m].
const std::string & getID() const
Returns the id.
Position getCenter() const
Returns the image center of the POI.
double getHeight() const
Returns the image height of the POI.
double getWidth() const
Returns the image width of the POI.
A point in 2D or 3D with translation and scaling methods.
double x() const
Returns the x-position.
double z() const
Returns the z-position.
double y() const
Returns the y-position.
double rotationDegreeAtOffset(double pos) const
Returns the rotation at the given length.
void move2side(double amount, double maxExtension=100)
move position vector to side using certain amount
bool hasElevation() const
return whether two positions differ in z-coordinate
unsigned char red() const
Returns the red-amount of the color.
unsigned char green() const
Returns the green-amount of the color.
unsigned char blue() const
Returns the blue-amount of the color.
void set(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
assigns new values
const PositionVector & getShape() const
Returns the shape of the polygon.
const std::vector< PositionVector > & getHoles() const
Returns the holers of the polygon.
const RGBColor & getShapeColor() const
Returns the color of the Shape.
A decal (an image) that can be shown.
double tilt
The tilt of the image to the ground plane (in degrees)
double centerX
The center of the image in x-direction (net coordinates, in m)
double height
The height of the image (net coordinates in y-direction, in m)
double width
The width of the image (net coordinates in x-direction, in m)
double rot
The rotation of the image in the ground plane (in degrees)
double layer
The layer of the image.
double altitude
The altitude of the image (net coordinates in z-direction, in m)
double centerY
The center of the image in y-direction (net coordinates, in m)
double centerZ
The center of the image in z-direction (net coordinates, in m)
std::string filename
The path to the file the image is located at.
double roll
The roll of the image to the ground plane (in degrees)