Eclipse SUMO - Simulation of Urban MObility
GNETLSEditorFrame.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
18 // The Widget for modifying traffic lights
19 /****************************************************************************/
20 #include <config.h>
21 
25 #include <utils/xml/XMLSubSys.h>
28 #include <netedit/GNEViewNet.h>
29 #include <netedit/GNENet.h>
30 #include <netedit/GNEUndoList.h>
33 
34 #include "GNETLSEditorFrame.h"
35 
36 // ===========================================================================
37 // FOX callback mapping
38 // ===========================================================================
39 
40 FXDEFMAP(GNETLSEditorFrame) GNETLSEditorFrameMap[] = {
41  FXMAPFUNC(SEL_COMMAND, MID_CANCEL, GNETLSEditorFrame::onCmdCancel),
42  FXMAPFUNC(SEL_UPDATE, MID_CANCEL, GNETLSEditorFrame::onUpdModified),
43  FXMAPFUNC(SEL_COMMAND, MID_OK, GNETLSEditorFrame::onCmdOK),
44  FXMAPFUNC(SEL_UPDATE, MID_OK, GNETLSEditorFrame::onUpdModified),
73 };
74 
80 };
81 
82 // Object implementation
83 FXIMPLEMENT(GNETLSEditorFrame, FXVerticalFrame, GNETLSEditorFrameMap, ARRAYNUMBER(GNETLSEditorFrameMap))
84 FXIMPLEMENT(GNETLSEditorFrame::TLSFile, FXGroupBox, TLSFileMap, ARRAYNUMBER(TLSFileMap))
85 
86 
87 // ===========================================================================
88 // method definitions
89 // ===========================================================================
90 
91 GNETLSEditorFrame::GNETLSEditorFrame(FXHorizontalFrame* horizontalFrameParent, GNEViewNet* viewNet):
92  GNEFrame(horizontalFrameParent, viewNet, "Edit Traffic Light"),
93  myEditedDef(nullptr) {
94 
95  // Create Overlapped Inspection modul
96  myOverlappedInspection = new GNEFrameModuls::OverlappedInspection(this, SUMO_TAG_JUNCTION);
97 
98  // create TLSJunction modul
99  myTLSJunction = new GNETLSEditorFrame::TLSJunction(this);
100 
101  // create TLSDefinition modul
102  myTLSDefinition = new GNETLSEditorFrame::TLSDefinition(this);
103 
104  // create TLSAttributes modul
105  myTLSAttributes = new GNETLSEditorFrame::TLSAttributes(this);
106 
107  // create TLSModifications modul
108  myTLSModifications = new GNETLSEditorFrame::TLSModifications(this);
109 
110  // create TLSPhases modul
111  myTLSPhases = new GNETLSEditorFrame::TLSPhases(this);
112 
113  // create TLSFile modul
114  myTLSFile = new GNETLSEditorFrame::TLSFile(this);
115 
116  // "Add 'off' program"
117  /*
118  new FXButton(myContentFrame, "Add \"Off\"-Program\t\tAdds a program for switching off this traffic light",
119  0, this, MID_GNE_TLSFRAME_ADDOFF, GUIDesignButton);
120  */
121 }
122 
123 
125  cleanup();
126 }
127 
128 
129 void
131  // hide myOverlappedInspection
133  GNEFrame::show();
134 }
135 
136 void
137 GNETLSEditorFrame::editTLS(const Position& clickedPosition, const GNEViewNetHelper::ObjectsUnderCursor& objectsUnderCursor) {
138  // first check if in objectsUnderCursor there is a junction
139  if (objectsUnderCursor.getJunctionFront()) {
140  // show objects under cursor
141  myOverlappedInspection->showOverlappedInspection(objectsUnderCursor, clickedPosition);
142  // hide if we inspect only one junction
145  }
146  // set junction
147  editJunction(objectsUnderCursor.getJunctionFront());
148  } else {
149  myViewNet->setStatusBarText("Click over a junction to edit a TLS");
150  }
151 }
152 
153 
154 bool
157  // write warning if netedit is running in testing mode
158  WRITE_DEBUG("Opening question FXMessageBox 'save TLS'");
159  // open question box
160  FXuint answer = FXMessageBox::question(this, MBOX_YES_NO_CANCEL,
161  "Save TLS Changes", "%s",
162  "There is unsaved changes in current edited traffic light.\nDo you want to save it before changing mode?");
163  if (answer == MBOX_CLICKED_YES) { //1:yes, 2:no, 4:esc/cancel
164  // write warning if netedit is running in testing mode
165  WRITE_DEBUG("Closed FXMessageBox 'save TLS' with 'YES'");
166  // save modifications
167  onCmdOK(nullptr, 0, nullptr);
168  return true;
169  } else if (answer == MBOX_CLICKED_NO) {
170  // write warning if netedit is running in testing mode
171  WRITE_DEBUG("Closed FXMessageBox 'save TLS' with 'No'");
172  // cancel modifications
173  onCmdCancel(nullptr, 0, nullptr);
174  return true;
175  } else {
176  // write warning if netedit is running in testing mode
177  WRITE_DEBUG("Closed FXMessageBox 'save TLS' with 'Cancel'");
178  // abort changing mode
179  return false;
180  }
181  } else {
182  return true;
183  }
184 }
185 
186 
187 bool
188 GNETLSEditorFrame::parseTLSPrograms(const std::string& file) {
190  NBTrafficLightLogicCont tmpTLLCont;
191  NIXMLTrafficLightsHandler tllHandler(tmpTLLCont, myViewNet->getNet()->getEdgeCont());
192  // existing definitions must be available to update their programs
193  std::set<NBTrafficLightDefinition*> origDefs;
194  for (NBTrafficLightDefinition* def : tllCont.getDefinitions()) {
195  // make a copy of every program
196  NBTrafficLightLogic* logic = tllCont.getLogic(def->getID(), def->getProgramID());
197  if (logic != nullptr) {
198  NBTrafficLightDefinition* copy = new NBLoadedSUMOTLDef(*def, *logic);
199  std::vector<NBNode*> nodes = def->getNodes();
200  for (auto it_node : nodes) {
201  GNEJunction* junction = myViewNet->getNet()->retrieveJunction(it_node->getID());
202  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, def, false, false), true);
203  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, copy, true), true);
204  }
205  tmpTLLCont.insert(copy);
206  origDefs.insert(copy);
207  } else {
208  WRITE_WARNING("tlLogic '" + def->getID() + "', program '" + def->getProgramID() + "' could not be built");
209  }
210  }
211  //std::cout << " initialized tmpCont with " << origDefs.size() << " defs\n";
212  XMLSubSys::runParser(tllHandler, file);
213 
214  std::vector<NBLoadedSUMOTLDef*> loadedTLS;
215  for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
216  NBLoadedSUMOTLDef* sdef = dynamic_cast<NBLoadedSUMOTLDef*>(def);
217  if (sdef != nullptr) {
218  loadedTLS.push_back(sdef);
219  }
220  }
221  myViewNet->setStatusBarText("Loaded " + toString(loadedTLS.size()) + " programs");
222  for (auto def : loadedTLS) {
223  if (origDefs.count(def) != 0) {
224  // already add to undolist before
225  //std::cout << " skip " << def->getDescription() << "\n";
226  continue;
227  }
228  std::vector<NBNode*> nodes = def->getNodes();
229  //std::cout << " add " << def->getDescription() << " for nodes=" << toString(nodes) << "\n";
230  for (auto it_node : nodes) {
231  GNEJunction* junction = myViewNet->getNet()->retrieveJunction(it_node->getID());
232  //myViewNet->getUndoList()->add(new GNEChange_TLS(junction, myTLSEditorParent->myEditedDef, false), true);
233  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, def, true), true);
234  }
235  }
236  // clean up temporary container to avoid deletion of defs when it's destruct is called
237  for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
238  tmpTLLCont.removeProgram(def->getID(), def->getProgramID(), false);
239  }
240  return true;
241 }
242 
243 
244 long
245 GNETLSEditorFrame::onCmdCancel(FXObject*, FXSelector, void*) {
246  if (myTLSJunction->getCurrentJunction() != nullptr) {
248  cleanup();
250  }
251  return 1;
252 }
253 
254 
255 long
256 GNETLSEditorFrame::onCmdOK(FXObject*, FXSelector, void*) {
257  if (myTLSJunction->getCurrentJunction() != nullptr) {
260  std::vector<NBNode*> nodes = oldDefinition->getNodes();
261  for (auto it : nodes) {
262  GNEJunction* junction = myViewNet->getNet()->retrieveJunction(it->getID());
263  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, oldDefinition, false), true);
264  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, myEditedDef, true), true);
265  }
266  myEditedDef = nullptr;
268  cleanup();
270  } else {
271  onCmdCancel(nullptr, 0, nullptr);
272  }
273  }
274  return 1;
275 }
276 
277 
278 long
279 GNETLSEditorFrame::onCmdDefCreate(FXObject*, FXSelector, void*) {
281  // abort because we onCmdOk assumes we wish to save an edited definition
282  onCmdCancel(nullptr, 0, nullptr);
283  // check that current junction has two or more edges
284  if ((junction->getGNEIncomingEdges().size() > 0) && (junction->getGNEOutgoingEdges().size() > 0)) {
287  } else {
288  if (junction->getNBNode()->isTLControlled()) {
289  // use existing traffic light as template for type, signal groups, controlled nodes etc
290  NBTrafficLightDefinition* tpl = *junction->getNBNode()->getControllingTLS().begin();
292  NBLoadedSUMOTLDef* newDef = new NBLoadedSUMOTLDef(*tpl, *newLogic);
293  delete newLogic;
294  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, newDef, true, true), true);
295  } else {
296  // for some reason the traffic light was not built, try again
297  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, nullptr, true, true), true);
298  }
299  }
300  editJunction(junction);
301  } else {
302  // write warning if netedit is running in testing mode
303  WRITE_DEBUG("Opening warning FXMessageBox 'invalid TLS'");
304  // open question box
305  FXMessageBox::warning(this, MBOX_OK,
306  "TLS cannot be created", "%s",
307  "Traffic Light cannot be created because junction must have\n at least one incoming edge and one outgoing edge.");
308  // write warning if netedit is running in testing mode
309  WRITE_DEBUG("Closed FXMessageBox 'invalid TLS'");
310  }
311  return 1;
312 }
313 
314 
315 long
316 GNETLSEditorFrame::onCmdDefDelete(FXObject*, FXSelector, void*) {
318  const bool changeType = myTLSAttributes->getNumberOfTLSDefinitions() == 1;
320  onCmdCancel(nullptr, 0, nullptr); // abort because onCmdOk assumes we wish to save an edited definition
321  if (changeType) {
323  } else {
324  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, tlDef, false), true);
325  }
326  return 1;
327 }
328 
329 
330 long
331 GNETLSEditorFrame::onCmdDefSwitch(FXObject*, FXSelector, void*) {
332  assert(myTLSJunction->getCurrentJunction() != 0);
335  // logic may not have been recomputed yet. recompute to be sure
338  NBTrafficLightLogic* tllogic = tllCont.getLogic(tlDef->getID(), tlDef->getProgramID());
339  if (tllogic != nullptr) {
340  // now we can be sure that the tlDef is up to date (i.e. re-guessed)
341  buildInternalLanes(tlDef);
342  // create working copy from original def
343  delete myEditedDef;
344  myEditedDef = new NBLoadedSUMOTLDef(*tlDef, *tllogic);
349  } else {
350  // tlDef has no valid logic (probably because id does not control any links
351  onCmdCancel(nullptr, 0, nullptr);
352  myViewNet->setStatusBarText("Traffic light does not control any links");
353  }
354  return 1;
355 }
356 
357 
358 long
359 GNETLSEditorFrame::onUpdDefSwitch(FXObject* o, FXSelector, void*) {
361  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
362  return 1;
363 }
364 
365 
366 long
367 GNETLSEditorFrame::onUpdNeedsDef(FXObject* o, FXSelector, void*) {
368  const bool enable = myTLSAttributes->getNumberOfTLSDefinitions() > 0;
369  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
370  return 1;
371 }
372 
373 
374 long
375 GNETLSEditorFrame::onUpdNeedsDefAndPhase(FXObject* o, FXSelector, void*) {
376  // do not delete the last phase
377  const bool enable = myTLSAttributes->getNumberOfTLSDefinitions() > 0 && myTLSPhases->getPhaseTable()->getNumRows() > 1;
378  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
379  return 1;
380 }
381 
382 
383 long
384 GNETLSEditorFrame::onUpdDefCreate(FXObject* o, FXSelector, void*) {
386  const bool enable = junction != nullptr && !myTLSModifications->checkHaveModifications();
387  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
388  const bool copy = junction != nullptr && junction->getNBNode()->isTLControlled();
389  static_cast<FXButton*>(o)->setText(copy ? "Copy" : "Create");
390  return 1;
391 }
392 
393 
394 long
395 GNETLSEditorFrame::onUpdModified(FXObject* o, FXSelector, void*) {
397  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
398  return 1;
399 }
400 
401 
402 
403 long
404 GNETLSEditorFrame::onCmdDefOffset(FXObject*, FXSelector, void*) {
407  return 1;
408 }
409 
410 
411 long
412 GNETLSEditorFrame::onCmdDefRename(FXObject*, FXSelector, void*) {
413  return 1;
414 }
415 
416 
417 long
418 GNETLSEditorFrame::onCmdDefSubRename(FXObject*, FXSelector, void*) {
419  return 1;
420 }
421 
422 
423 long
424 GNETLSEditorFrame::onCmdDefAddOff(FXObject*, FXSelector, void*) {
425  return 1;
426 }
427 
428 
429 long
430 GNETLSEditorFrame::onCmdGuess(FXObject*, FXSelector, void*) {
431  return 1;
432 }
433 
434 
435 long
436 GNETLSEditorFrame::onCmdPhaseSwitch(FXObject*, FXSelector, void*) {
437  const int index = myTLSPhases->getPhaseTable()->getCurrentRow();
438  const NBTrafficLightLogic::PhaseDefinition& phase = getPhases()[index];
439  myTLSPhases->getPhaseTable()->selectRow(index);
440  // need not hold since links could have been deleted somewhere else and indices may be reused
441  // assert(phase.state.size() == myInternalLanes.size());
442  for (auto it : myInternalLanes) {
443  int tlIndex = it.first;
444  std::vector<GNEInternalLane*> lanes = it.second;
446  if (tlIndex >= 0 && tlIndex < (int)phase.state.size()) {
447  state = (LinkState)phase.state[tlIndex];
448  }
449  for (auto it_lane : lanes) {
450  it_lane->setLinkState(state);
451  }
452  }
454  return 1;
455 }
456 
457 
458 bool
460  assert(myEditedDef != nullptr);
462 }
463 
464 
465 void
467  editJunction(dynamic_cast<GNEJunction*>(AC));
468 }
469 
470 
471 long
472 GNETLSEditorFrame::onCmdPhaseCreate(FXObject*, FXSelector, void*) {
474  // allows insertion at first position by deselecting via arrow keys
475  int newIndex = myTLSPhases->getPhaseTable()->getSelStartRow() + 1;
476  int oldIndex = MAX2(0, myTLSPhases->getPhaseTable()->getSelStartRow());
477  // copy current row
478  SUMOTime duration = getSUMOTime(myTLSPhases->getPhaseTable()->getItemText(oldIndex, 0));
479  const std::string oldState = myTLSPhases->getPhaseTable()->getItemText(oldIndex, fixedDuration() ? 1 : 3).text();
480  std::string state = oldState;
481 
482  std::set<int> crossingIndices;
483  for (NBNode* n : myEditedDef->getNodes()) {
484  for (NBNode::Crossing* c : n->getCrossings()) {
485  crossingIndices.insert(c->tlLinkIndex);
486  crossingIndices.insert(c->tlLinkIndex2);
487  }
488  }
489 
490  // smart adapations for new state
491  bool haveGreen = false;
492  bool haveYellow = false;
493  for (char c : state) {
495  haveGreen = true;
496  } else if (c == LINKSTATE_TL_YELLOW_MAJOR || c == LINKSTATE_TL_YELLOW_MINOR) {
497  haveYellow = true;
498  }
499  }
500  const OptionsCont& oc = OptionsCont::getOptions();
501  if (haveGreen && haveYellow) {
502  // guess left-mover state
503  duration = TIME2STEPS(oc.getInt("tls.left-green.time"));
504  for (int i = 0; i < (int)state.size(); i++) {
505  if (state[i] == LINKSTATE_TL_YELLOW_MAJOR || state[i] == LINKSTATE_TL_YELLOW_MINOR) {
506  state[i] = LINKSTATE_TL_RED;
507  } else if (state[i] == LINKSTATE_TL_GREEN_MINOR) {
508  state[i] = LINKSTATE_TL_GREEN_MAJOR;
509  }
510  }
511  } else if (haveGreen) {
512  // guess yellow state
514  duration = TIME2STEPS(myEditedDef->computeBrakingTime(oc.getFloat("tls.yellow.min-decel")));
515  for (int i = 0; i < (int)state.size(); i++) {
516  if (state[i] == LINKSTATE_TL_GREEN_MAJOR || state[i] == LINKSTATE_TL_GREEN_MINOR) {
517  if (crossingIndices.count(i) == 0) {
518  state[i] = LINKSTATE_TL_YELLOW_MINOR;
519  } else {
520  state[i] = LINKSTATE_TL_RED;
521  }
522  }
523  }
524  } else if (haveYellow) {
525  duration = TIME2STEPS(oc.isDefault("tls.allred.time") ? 2 : oc.getInt("tls.allred.time"));
526  // guess all-red state
527  for (int i = 0; i < (int)state.size(); i++) {
528  if (state[i] == LINKSTATE_TL_YELLOW_MAJOR || state[i] == LINKSTATE_TL_YELLOW_MINOR) {
529  state[i] = LINKSTATE_TL_RED;
530  }
531  }
532  }
533  // fix continuous green states
534  const int nextIndex = myTLSPhases->getPhaseTable()->getNumRows() > newIndex ? newIndex : 0;
535  const std::string state2 = myTLSPhases->getPhaseTable()->getItemText(nextIndex, fixedDuration() ? 1 : 3).text();
536  for (int i = 0; i < (int)state.size(); i++) {
537  if ((oldState[i] == LINKSTATE_TL_GREEN_MAJOR || oldState[i] == LINKSTATE_TL_GREEN_MINOR)
538  && (state2[i] == LINKSTATE_TL_GREEN_MAJOR || state2[i] == LINKSTATE_TL_GREEN_MINOR)) {
539  state[i] = oldState[i];
540  }
541  }
542 
543  myEditedDef->getLogic()->addStep(duration, state, std::vector<int>(), "", newIndex);
544  myTLSPhases->getPhaseTable()->setCurrentItem(newIndex, 0);
545  myTLSPhases->initPhaseTable(newIndex);
546  myTLSPhases->getPhaseTable()->setFocus();
547  return 1;
548 }
549 
550 
551 long
552 GNETLSEditorFrame::onCmdPhaseDelete(FXObject*, FXSelector, void*) {
554  const int newRow = MAX2((int)0, (int)myTLSPhases->getPhaseTable()->getCurrentRow() - 1);
555  myEditedDef->getLogic()->deletePhase(myTLSPhases->getPhaseTable()->getCurrentRow());
556  myTLSPhases->initPhaseTable(newRow);
557  myTLSPhases->getPhaseTable()->setFocus();
558  return 1;
559 }
560 
561 
562 long
563 GNETLSEditorFrame::onCmdCleanup(FXObject*, FXSelector, void*) {
567  myTLSPhases->getPhaseTable()->setFocus();
569  return 1;
570 }
571 
572 
573 long
574 GNETLSEditorFrame::onCmdAddUnused(FXObject*, FXSelector, void*) {
576  myEditedDef->getLogic()->getNumLinks() + 1);
579  myTLSPhases->getPhaseTable()->setFocus();
580  return 1;
581 }
582 
583 
584 long
585 GNETLSEditorFrame::onCmdGroupStates(FXObject*, FXSelector, void*) {
590  myTLSPhases->getPhaseTable()->setFocus();
591  return 1;
592 }
593 
594 
595 long
596 GNETLSEditorFrame::onCmdUngroupStates(FXObject*, FXSelector, void*) {
602  myTLSPhases->getPhaseTable()->setFocus();
603  return 1;
604 }
605 
606 
607 long
608 GNETLSEditorFrame::onUpdNeedsSingleDef(FXObject* o, FXSelector, void*) {
609  const bool enable = myTLSAttributes->getNumberOfTLSDefinitions() == 1;
610  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
611  return 1;
612 }
613 
614 long
615 GNETLSEditorFrame::onUpdUngroupStates(FXObject* o, FXSelector, void*) {
616  const bool enable = myTLSAttributes->getNumberOfTLSDefinitions() == 1 && myEditedDef != nullptr && myEditedDef->usingSignalGroups();
617  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
618  return 1;
619 }
620 
621 long
622 GNETLSEditorFrame::onCmdPhaseEdit(FXObject*, FXSelector, void* ptr) {
623  /* @note: there is a bug when copying/pasting rows: when this handler is
624  * called the value of the cell is not yet updated. This means you have to
625  * click inside the cell and hit enter to actually update the value */
626  FXTablePos* tp = (FXTablePos*)ptr;
627  FXString value = myTLSPhases->getPhaseTable()->getItemText(tp->row, tp->col);
628  const int colDuration = 0;
629  const int colMinDur = fixedDuration() ? -1 : 1;
630  const int colMaxDur = fixedDuration() ? -1 : 2;
631  const int colState = fixedDuration() ? 1 : 3;
632  const int colNext = fixedDuration() ? 2 : 4;
633  const int colName = fixedDuration() ? 3 : 5;
634 
635  if (tp->col == colDuration) {
636  // duration edited
637  if (GNEAttributeCarrier::canParse<double>(value.text())) {
638  SUMOTime duration = getSUMOTime(value);
639  if (duration > 0) {
640  myEditedDef->getLogic()->setPhaseDuration(tp->row, duration);
643  return 1;
644  }
645  }
646  // input error, reset value
647  myTLSPhases->getPhaseTable()->setItemText(tp->row, colDuration, toString(STEPS2TIME(getPhases()[tp->row].duration)).c_str());
648  } else if (tp->col == colMinDur) {
649  // minDur edited
650  if (GNEAttributeCarrier::canParse<double>(value.text())) {
651  SUMOTime minDur = getSUMOTime(value);
652  if (minDur > 0) {
653  myEditedDef->getLogic()->setPhaseMinDuration(tp->row, minDur);
655  return 1;
656  }
657  } else if (StringUtils::prune(value.text()).empty()) {
660  return 1;
661  }
662  // input error, reset value
663  myTLSPhases->getPhaseTable()->setItemText(tp->row, colMinDur, varDurString(getPhases()[tp->row].minDur).c_str());
664  } else if (tp->col == colMaxDur) {
665  // maxDur edited
666  if (GNEAttributeCarrier::canParse<double>(value.text())) {
667  SUMOTime maxDur = getSUMOTime(value);
668  if (maxDur > 0) {
669  myEditedDef->getLogic()->setPhaseMaxDuration(tp->row, maxDur);
671  return 1;
672  }
673  } else if (StringUtils::prune(value.text()).empty()) {
676  return 1;
677  }
678  // input error, reset value
679  myTLSPhases->getPhaseTable()->setItemText(tp->row, colMaxDur, varDurString(getPhases()[tp->row].maxDur).c_str());
680  } else if (tp->col == colState) {
681  // state edited
682  try {
683  // insert phase with new step and delete the old phase
684  const NBTrafficLightLogic::PhaseDefinition& phase = getPhases()[tp->row];
685  myEditedDef->getLogic()->addStep(phase.duration, value.text(), phase.next, phase.name, tp->row);
686  myEditedDef->getLogic()->deletePhase(tp->row + 1);
688  onCmdPhaseSwitch(nullptr, 0, nullptr);
689  } catch (ProcessError&) {
690  // input error, reset value
691  myTLSPhases->getPhaseTable()->setItemText(tp->row, colState, getPhases()[tp->row].state.c_str());
692  }
693  } else if (tp->col == colNext) {
694  // next edited
695  bool ok = true;
696  if (GNEAttributeCarrier::canParse<std::vector<int> >(value.text())) {
697  std::vector<int> nextEdited = GNEAttributeCarrier::parse<std::vector<int> >(value.text());
698  for (int n : nextEdited) {
699  if (n < 0 || n >= myTLSPhases->getPhaseTable()->getNumRows()) {
700  ok = false;
701  break;
702  }
703  }
704  if (ok) {
705  myEditedDef->getLogic()->setPhaseNext(tp->row, nextEdited);
707  return 1;
708  }
709  }
710  // input error, reset value
711  myTLSPhases->getPhaseTable()->setItemText(tp->row, colNext, "");
712  } else if (tp->col == colName) {
713  // name edited
714  myEditedDef->getLogic()->setPhaseName(tp->row, value.text());
716  return 1;
717  }
718  return 1;
719 }
720 
721 
722 void
728  myViewNet->getNet()->retrieveJunction(node->getID())->selectTLS(false);
729  }
730  }
731  }
732  // clean data structures
735  delete myEditedDef;
736  myEditedDef = nullptr;
737  // clear internal lanes
738  buildInternalLanes(nullptr);
739  // clean up controls
741  // only clears when there are no definitions
745 }
746 
747 
748 void
750  // clean up previous internal lanes
751  for (const auto& internalLanes : myInternalLanes) {
752  for (const auto& internalLane : internalLanes.second) {
753  // remove internal lane from grid
754  myViewNet->getNet()->getGrid().removeAdditionalGLObject(internalLane);
755  // delete internal lane
756  delete internalLane;
757  }
758  }
759  // clear container
760  myInternalLanes.clear();
761  // create new internal lanes
762  if (tlDef != nullptr) {
763  const int NUM_POINTS = 10;
764  const NBNode* nbnCurrentJunction = myTLSJunction->getCurrentJunction()->getNBNode();
765  // get innerID NWWriter_SUMO::writeInternalEdges
766  const std::string innerID = ":" + nbnCurrentJunction->getID();
767  const NBConnectionVector& links = tlDef->getControlledLinks();
768  // iterate over links
769  for (const auto& link : links) {
770  int tlIndex = link.getTLIndex();
771  PositionVector shape = link.getFrom()->getToNode()->computeInternalLaneShape(link.getFrom(), NBEdge::Connection(link.getFromLane(),
772  link.getTo(), link.getToLane()), NUM_POINTS);
773  if (shape.length() < 2) {
774  // enlarge shape to ensure visibility
775  shape.clear();
776  const PositionVector laneShapeFrom = link.getFrom()->getLaneShape(link.getFromLane());
777  const PositionVector laneShapeTo = link.getTo()->getLaneShape(link.getToLane());
778  shape.push_back(laneShapeFrom.positionAtOffset(MAX2(0.0, laneShapeFrom.length() - 1)));
779  shape.push_back(laneShapeTo.positionAtOffset(MIN2(1.0, laneShapeFrom.length())));
780  }
781  GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), innerID + '_' + toString(tlIndex), shape, tlIndex);
782  // due GNEInternalLane aren't attribute carriers, we need to use the net grid
783  myViewNet->getNet()->getGrid().addAdditionalGLObject(internalLane);
784  myInternalLanes[tlIndex].push_back(internalLane);
785  }
786  // iterate over crossings
787  for (const auto& nbn : tlDef->getNodes()) {
788  for (const auto& crossing : nbn->getCrossings()) {
789  if (crossing->tlLinkIndex2 > 0 && crossing->tlLinkIndex2 != crossing->tlLinkIndex) {
790  // draw both directions
791  PositionVector forward = crossing->shape;
792  forward.move2side(crossing->width / 4);
793  GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id, forward, crossing->tlLinkIndex);
794  // due GNEInternalLane aren't attribute carriers, we need to use the net grid
795  myViewNet->getNet()->getGrid().addAdditionalGLObject(internalLane);
796  myInternalLanes[crossing->tlLinkIndex].push_back(internalLane);
797  PositionVector backward = crossing->shape.reverse();
798  backward.move2side(crossing->width / 4);
799  GNEInternalLane* internalLaneReverse = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id + "_r", backward, crossing->tlLinkIndex2);
800  // due GNEInternalLane aren't attribute carriers, we need to use the net grid
801  myViewNet->getNet()->getGrid().addAdditionalGLObject(internalLaneReverse);
802  myInternalLanes[crossing->tlLinkIndex2].push_back(internalLaneReverse);
803  } else {
804  // draw only one lane for both directions
805  GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id, crossing->shape, crossing->tlLinkIndex);
806  // due GNEInternalLane aren't attribute carriers, we need to use the net grid
807  myViewNet->getNet()->getGrid().addAdditionalGLObject(internalLane);
808  myInternalLanes[crossing->tlLinkIndex].push_back(internalLane);
809  }
810  }
811  }
812  }
813 }
814 
815 
816 std::string
819 }
820 
821 
822 const std::vector<NBTrafficLightLogic::PhaseDefinition>&
824  return myEditedDef->getLogic()->getPhases();
825 }
826 
827 
828 void
831  if (myViewNet->changeAllPhases()) {
832  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = getPhases();
833  for (int row = 0; row < (int)phases.size(); row++) {
834  myEditedDef->getLogic()->setPhaseState(row, lane->getTLIndex(), lane->getLinkState());
835  }
836  } else {
837  myEditedDef->getLogic()->setPhaseState(myTLSPhases->getPhaseTable()->getCurrentRow(), lane->getTLIndex(), lane->getLinkState());
838  }
839  myTLSPhases->initPhaseTable(myTLSPhases->getPhaseTable()->getCurrentRow());
840  myTLSPhases->getPhaseTable()->setFocus();
841 }
842 
843 
844 void
845 GNETLSEditorFrame::handleMultiChange(GNELane* lane, FXObject* obj, FXSelector sel, void* eventData) {
846  if (myEditedDef != nullptr) {
849  std::set<std::string> fromIDs;
850  fromIDs.insert(lane->getMicrosimID());
851  // if neither the lane nor its edge are selected, apply changes to the whole edge
853  for (auto it_lane : lane->getParentEdge()->getLanes()) {
854  fromIDs.insert(it_lane->getMicrosimID());
855  }
856  } else {
857  // if the edge is selected, apply changes to all lanes of all selected edges
858  if (lane->getParentEdge()->isAttributeCarrierSelected()) {
859  std::vector<GNEEdge*> edges = myViewNet->getNet()->retrieveEdges(true);
860  for (auto it : edges) {
861  for (auto it_lane : it->getLanes()) {
862  fromIDs.insert(it_lane->getMicrosimID());
863  }
864  }
865  }
866  // if the lane is selected, apply changes to all selected lanes
867  if (lane->isAttributeCarrierSelected()) {
868  std::vector<GNELane*> lanes = myViewNet->getNet()->retrieveLanes(true);
869  for (auto it_lane : lanes) {
870  fromIDs.insert(it_lane->getMicrosimID());
871  }
872  }
873 
874  }
875  // set new state for all connections from the chosen lane IDs
876  for (auto it : links) {
877  if (fromIDs.count(it.getFrom()->getLaneID(it.getFromLane())) > 0) {
878  std::vector<GNEInternalLane*> lanes = myInternalLanes[it.getTLIndex()];
879  for (auto it_lane : lanes) {
880  it_lane->onDefault(obj, sel, eventData);
881  }
882  }
883  }
884  }
885 }
886 
887 
888 bool
890  if (myEditedDef != nullptr) {
892  for (auto it : links) {
893  if (it.getFrom()->getID() == edge->getMicrosimID()) {
894  return true;
895  }
896  }
897  }
898  return false;
899 }
900 
901 
902 void
905  onCmdCancel(nullptr, 0, nullptr);
906  myViewNet->getUndoList()->p_begin("modifying traffic light definition");
910  // only select TLS if getCurrentJunction exist
913  }
916  myViewNet->getNet()->retrieveJunction(node->getID())->selectTLS(true);
917  }
918  }
919  } else {
920  myViewNet->setStatusBarText("Unsaved modifications. Abort or Save");
921  }
922 }
923 
924 
925 SUMOTime
926 GNETLSEditorFrame::getSUMOTime(const FXString& string) {
927  return TIME2STEPS(GNEAttributeCarrier::parse<double>(string.text()));
928 }
929 
930 // ---------------------------------------------------------------------------
931 // GNETLSEditorFrame::TLSAttributes - methods
932 // ---------------------------------------------------------------------------
933 
935  FXGroupBox(TLSEditorParent->myContentFrame, "Traffic light Attributes", GUIDesignGroupBoxFrame),
936  myTLSEditorParent(TLSEditorParent) {
937 
938  // create frame, label and textfield for name (By default disabled)
939  FXHorizontalFrame* nameFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
940  myNameLabel = new FXLabel(nameFrame, "ID", nullptr, GUIDesignLabelAttribute);
942  myNameTextField->disable();
943 
944  // create frame, label and comboBox for Program (By default hidden)
945  FXHorizontalFrame* programFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
946  myProgramLabel = new FXLabel(programFrame, "Program", nullptr, GUIDesignLabelAttribute);
948  myProgramComboBox->disable();
949 
950  // create frame, label and TextField for Offset (By default disabled)
951  FXHorizontalFrame* offsetFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
952  myOffsetLabel = new FXLabel(offsetFrame, "Offset", nullptr, GUIDesignLabelAttribute);
954  myOffsetTextField->disable();
955 }
956 
957 
959 
960 
961 void
963  assert(junction);
964  myTLSDefinitions.clear();
965  // enable name TextField
966  myNameTextField->enable();
967  // enable Offset
968  myOffsetTextField->enable();
969  // obtain TLSs
970  for (auto it : junction->getNBNode()->getControllingTLS()) {
971  myTLSDefinitions.push_back(it);
972  myNameTextField->setText(it->getID().c_str());
973  myNameTextField->enable();
974  myProgramComboBox->appendItem(it->getProgramID().c_str());
975  }
976  if (myTLSDefinitions.size() > 0) {
977  myProgramComboBox->enable();
978  myProgramComboBox->setCurrentItem(0);
979  myProgramComboBox->setNumVisible(myProgramComboBox->getNumItems());
980  myTLSEditorParent->onCmdDefSwitch(nullptr, 0, nullptr);
981  }
982 }
983 
984 
985 void
987  // clear definitions
988  myTLSDefinitions.clear();
989  // clear and disable name TextField
990  myNameTextField->setText("");
991  myNameTextField->disable();
992  // clear and disable myProgramComboBox
993  myProgramComboBox->clearItems();
994  myProgramComboBox->disable();
995  // clear and disable Offset TextField
996  myOffsetTextField->setText("");
997  myOffsetTextField->disable();
998 }
999 
1000 
1003  return myTLSDefinitions.at(myProgramComboBox->getCurrentItem());
1004 }
1005 
1006 
1007 int
1009  return (int)myTLSDefinitions.size();
1010 }
1011 
1012 
1013 int
1015  return myProgramComboBox->getNumItems();
1016 }
1017 
1018 
1019 SUMOTime
1021  return getSUMOTime(myOffsetTextField->getText());
1022 }
1023 
1024 
1025 void
1027  myOffsetTextField->setText(toString(STEPS2TIME(offset)).c_str());
1028 }
1029 
1030 // ---------------------------------------------------------------------------
1031 // GNETLSEditorFrame::TLSJunction - methods
1032 // ---------------------------------------------------------------------------
1033 
1035  FXGroupBox(tlsEditorParent->myContentFrame, "Junction", GUIDesignGroupBoxFrame),
1036  myCurrentJunction(nullptr) {
1037  // Create frame for junction ID
1038  FXHorizontalFrame* junctionIDFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
1039  myLabelJunctionID = new FXLabel(junctionIDFrame, "Junction ID", nullptr, GUIDesignLabelAttribute);
1041  myTextFieldJunctionID->setEditable(false);
1042  // update junction description after creation
1044  // show TLS Junction
1045  show();
1046 }
1047 
1048 
1050 
1051 
1052 GNEJunction*
1054  return myCurrentJunction;
1055 }
1056 
1057 
1058 void
1060  myCurrentJunction = junction;
1061 }
1062 
1063 
1064 void
1066  if (myCurrentJunction == nullptr) {
1067  myTextFieldJunctionID->setText("");
1068  } else {
1069  NBNode* nbn = myCurrentJunction->getNBNode();
1070  myTextFieldJunctionID->setText(nbn->getID().c_str());
1071  }
1072 }
1073 
1074 // ---------------------------------------------------------------------------
1075 // GNETLSEditorFrame::TLSDefinition - methods
1076 // ---------------------------------------------------------------------------
1077 
1079  FXGroupBox(TLSEditorParent->myContentFrame, "Traffic Light Programs", GUIDesignGroupBoxFrame) {
1080  FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
1081  // create create tlDef button
1082  myNewTLProgram = new FXButton(buttonsFrame, "Create\t\tCreate a new traffic light program",
1084  // create delete tlDef button
1085  myDeleteTLProgram = new FXButton(buttonsFrame, "Delete\t\tDelete a traffic light program. If all programs are deleted the junction turns into a priority junction.",
1087  // show TLS TLSDefinition
1088  show();
1089 }
1090 
1091 
1093 
1094 // ---------------------------------------------------------------------------
1095 // GNETLSEditorFrame::TLSPhases - methods
1096 // ---------------------------------------------------------------------------
1097 
1099  FXGroupBox(TLSEditorParent->myContentFrame, "Phases", GUIDesignGroupBoxFrame),
1100  myTLSEditorParent(TLSEditorParent),
1101  myTableFont(new FXFont(getApp(), "Courier New", 9)) {
1102 
1103  // create and configure phase table
1104  myTableScroll = new FXScrollWindow(this, LAYOUT_FILL_X | LAYOUT_FIX_HEIGHT);
1106  myPhaseTable->setColumnHeaderMode(LAYOUT_FIX_HEIGHT);
1107  myPhaseTable->setColumnHeaderHeight(getApp()->getNormalFont()->getFontHeight() + getApp()->getNormalFont()->getFontAscent() / 2);
1108  myPhaseTable->setRowHeaderMode(LAYOUT_FIX_WIDTH);
1109  myPhaseTable->setRowHeaderWidth(0);
1110  myPhaseTable->hide();
1111  myPhaseTable->setFont(myTableFont);
1112  myPhaseTable->setHelpText("phase duration in seconds | phase state");
1113 
1114  // create total duration info label
1115  myCycleDuration = new FXLabel(this, "", nullptr, GUIDesignLabelLeft);
1116 
1117  // using FXMatrix for tabular button layout would have been cleaner but the
1118  // below attempt did not make the buttons fill available horizontal space
1119  // FXMatrix* phaseButtons = new FXMatrix(this, 2, LAYOUT_FILL_X | MATRIX_BY_COLUMNS);
1120 
1121  FXHorizontalFrame* phaseButtons = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
1122  FXVerticalFrame* col1 = new FXVerticalFrame(phaseButtons, LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // left button columm
1123  FXVerticalFrame* col2 = new FXVerticalFrame(phaseButtons, LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // right button column
1124 
1125  // create new phase button
1126  myInsertDuplicateButton = new FXButton(col1, "Insert Phase\t\tInsert new phase after the selected phase. The new state is deduced from the selected phase.", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_PHASE_CREATE, GUIDesignButton);
1127  // create delete phase button
1128  myDeleteSelectedPhaseButton = new FXButton(col2, "Delete Phase\t\tDelete selected phase", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_PHASE_DELETE, GUIDesignButton);
1129 
1130  // create cleanup states button
1131  new FXButton(col1, "Clean States\t\tClean unused states from all phase. (Not allowed for multiple programs)", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_CLEANUP, GUIDesignButton);
1132 
1133  // add unused states button
1134  new FXButton(col2, "Add States\t\tExtend the state vector for all phases by one entry (unused until a connection or crossing is assigned to the new index).", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_ADDUNUSED, GUIDesignButton);
1135 
1136  // group states button
1137  new FXButton(col1, "Group Signals\t\tShorten state definition by letting connections with the same signal states use the same index. (Not allowed for multiple programs)", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_GROUP_STATES, GUIDesignButton);
1138 
1139  // ungroup states button
1140  new FXButton(col2, "Ungroup Signals\t\tLet every connection use a distinct index (reverse state grouping). (Not allowed for multiple programs)", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_UNGROUP_STATES, GUIDesignButton);
1141  // show TLSFile
1142  show();
1143 }
1144 
1145 
1147  delete myTableFont;
1148 }
1149 
1150 
1151 FXTable*
1153  return myPhaseTable;
1154 }
1155 
1156 
1157 void
1159  myPhaseTable->setVisibleRows(1);
1160  myPhaseTable->setVisibleColumns(2);
1161  myPhaseTable->hide();
1162  if (myTLSEditorParent->myTLSAttributes->getNumberOfTLSDefinitions() > 0) {
1163  const bool fixed = myTLSEditorParent->fixedDuration();
1164  const int cols = fixed ? 4 : 6;
1165  const int colDuration = 0;
1166  const int colMinDur = fixed ? -1 : 1;
1167  const int colMaxDur = fixed ? -1 : 2;
1168  const int colState = fixed ? 1 : 3;
1169  const int colNext = fixed ? 2 : 4;
1170  const int colName = fixed ? 3 : 5;
1171 
1172  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = myTLSEditorParent->getPhases();
1173  myPhaseTable->setTableSize((int)phases.size(), cols);
1174  myPhaseTable->setVisibleRows((int)phases.size());
1175  myPhaseTable->setVisibleColumns(cols);
1176  for (int row = 0; row < (int)phases.size(); row++) {
1177  myPhaseTable->setItemText(row, colDuration, toString(STEPS2TIME(phases[row].duration)).c_str());
1178  if (!fixed) {
1179  myPhaseTable->setItemText(row, colMinDur, varDurString(phases[row].minDur).c_str());
1180  myPhaseTable->setItemText(row, colMaxDur, varDurString(phases[row].maxDur).c_str());
1181  }
1182  myPhaseTable->setItemText(row, colState, phases[row].state.c_str());
1183  myPhaseTable->setItemText(row, colNext, phases[row].next.size() > 0 ? toString(phases[row].next).c_str() : " ");
1184  myPhaseTable->setItemText(row, colName, phases[row].name.c_str());
1185  myPhaseTable->getItem(row, 1)->setJustify(FXTableItem::LEFT);
1186  }
1187  myPhaseTable->fitColumnsToContents(0, cols);
1188  myPhaseTable->setColumnText(colDuration, "dur");
1189  if (colMinDur >= 0) {
1190  myPhaseTable->setColumnText(colMinDur, "min");
1191  myPhaseTable->setColumnText(colMaxDur, "max");
1192  myPhaseTable->setColumnWidth(colMinDur, MAX2(myPhaseTable->getColumnWidth(colMinDur), 30));
1193  myPhaseTable->setColumnWidth(colMaxDur, MAX2(myPhaseTable->getColumnWidth(colMaxDur), 35));
1194  }
1195  myPhaseTable->setColumnText(colState, "state");
1196  myPhaseTable->setColumnText(colNext, "nxt");
1197  myPhaseTable->setColumnText(colName, "name");
1198  myPhaseTable->setColumnWidth(colNext, MAX2(myPhaseTable->getColumnWidth(colNext), 30));
1199  myPhaseTable->setColumnWidth(colName, MAX2(myPhaseTable->getColumnWidth(colName), 45));
1200 
1201  myPhaseTable->setHeight((int)phases.size() * 21 + 21); // experimental
1202  myPhaseTable->setCurrentItem(index, 0);
1203  myPhaseTable->selectRow(index, true);
1204  myPhaseTable->show();
1205  myPhaseTable->setFocus();
1206  myTableScroll->setHeight(myPhaseTable->getHeight() + 15);
1207 
1208  // neither my myPhaseTable->getWidth nor getDefaultWidth return the sum of column widths
1209  // however, the scroll pane uses getDefaultWidth to determine the
1210  // horizontal scrolling area which can only be changed via
1211  // getDefColumnWidth, hence the baroque work-around
1212 
1213  int neededWidth = 0;
1214  for (int i = 0; i < cols; i++) {
1215  neededWidth += myPhaseTable->getColumnWidth(i);
1216  }
1217  myPhaseTable->setDefColumnWidth(neededWidth / cols);
1218  }
1219  update();
1220 }
1221 
1222 
1223 void
1225  myCycleDuration->show();
1226 }
1227 
1228 
1229 void
1231  myCycleDuration->hide();
1232 }
1233 
1234 void
1236  SUMOTime cycleDuration = 0;
1237  for (auto it : myTLSEditorParent->getPhases()) {
1238  cycleDuration += it.duration;
1239  }
1240  std::string text = "Cycle time: " + toString(STEPS2TIME(cycleDuration));
1241  myCycleDuration->setText(text.c_str());
1242 }
1243 
1244 // ---------------------------------------------------------------------------
1245 // GNETLSEditorFrame::TLSModifications - methods
1246 // ---------------------------------------------------------------------------
1247 
1249  FXGroupBox(TLSEditorParent->myContentFrame, "Modifications", GUIDesignGroupBoxFrame),
1250  myTLSEditorParent(TLSEditorParent),
1251  myHaveModifications(false) {
1252  FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
1253  // create save modifications button
1254  mySaveModificationsButtons = new FXButton(buttonsFrame, "Save\t\tSave program modifications (Enter)",
1256  // create discard modifications buttons
1257  myDiscardModificationsButtons = new FXButton(buttonsFrame, "Cancel\t\tDiscard program modifications (Esc)",
1259  // show TLSModifications
1260  show();
1261 }
1262 
1263 
1265 
1266 
1267 bool
1269  return myHaveModifications;
1270 }
1271 
1272 
1273 void
1275  myHaveModifications = value;
1276 }
1277 
1278 // ---------------------------------------------------------------------------
1279 // GNETLSEditorFrame::TLSFile - methods
1280 // ---------------------------------------------------------------------------
1281 
1283  FXGroupBox(TLSEditorParent->myContentFrame, "TLS Program File", GUIDesignGroupBoxFrame),
1284  myTLSEditorParent(TLSEditorParent) {
1285  FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
1286  // create create tlDef button
1287  myLoadTLSProgramButton = new FXButton(buttonsFrame, "Load\t\tLoad TLS program from additional file", GUIIconSubSys::getIcon(GUIIcon::OPEN_CONFIG), this, MID_GNE_TLSFRAME_LOAD_PROGRAM, GUIDesignButton);
1288  // create create tlDef button
1289  mySaveTLSProgramButton = new FXButton(buttonsFrame, "Save\t\tSave TLS program to additional file", GUIIconSubSys::getIcon(GUIIcon::SAVE), this, MID_GNE_TLSFRAME_SAVE_PROGRAM, GUIDesignButton);
1290  // show TLSFile
1291  show();
1292 }
1293 
1294 
1296 
1297 
1298 long
1300  FXFileDialog opendialog(this, "Load TLS Program");
1301  opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::MODETLS));
1302  opendialog.setSelectMode(SELECTFILE_EXISTING);
1303  opendialog.setPatternList("*.xml");
1304  if (gCurrentFolder.length() != 0) {
1305  opendialog.setDirectory(gCurrentFolder);
1306  }
1307  if (opendialog.execute()) {
1308  // run parser
1309  NBTrafficLightLogicCont tmpTLLCont;
1310  NIXMLTrafficLightsHandler tllHandler(tmpTLLCont, myTLSEditorParent->myViewNet->getNet()->getEdgeCont(), true);
1311  tmpTLLCont.insert(myTLSEditorParent->myEditedDef);
1312  XMLSubSys::runParser(tllHandler, opendialog.getFilename().text());
1313 
1314  NBLoadedSUMOTLDef* newDefSameProgram = nullptr;
1315  std::set<NBLoadedSUMOTLDef*> newDefsOtherProgram;
1316  for (auto item : tmpTLLCont.getPrograms(myTLSEditorParent->myEditedDef->getID())) {
1317  if (item.second != myTLSEditorParent->myEditedDef) {
1318  NBLoadedSUMOTLDef* sdef = dynamic_cast<NBLoadedSUMOTLDef*>(item.second);
1319  if (item.first == myTLSEditorParent->myEditedDef->getProgramID()) {
1320  newDefSameProgram = sdef;
1321  } else {
1322  newDefsOtherProgram.insert(sdef);
1323  }
1324  }
1325  }
1326  const int newPrograms = (int)newDefsOtherProgram.size();
1327  if (newPrograms > 0 || newDefSameProgram != nullptr) {
1328  std::vector<NBNode*> nodes = myTLSEditorParent->myEditedDef->getNodes();
1329  for (auto newProg : newDefsOtherProgram) {
1330  for (auto it_node : nodes) {
1331  GNEJunction* junction = myTLSEditorParent->getViewNet()->getNet()->retrieveJunction(it_node->getID());
1332  myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, newProg, true), true);
1333  }
1334  }
1335  if (newPrograms > 0) {
1336  WRITE_MESSAGE("Loaded " + toString(newPrograms) + " new programs for tlLogic '" + myTLSEditorParent->myEditedDef->getID() + "'");
1337  }
1338  if (newDefSameProgram != nullptr) {
1339  // replace old program when loading the same program ID
1340  myTLSEditorParent->myEditedDef = newDefSameProgram;
1341  WRITE_MESSAGE("Updated program '" + newDefSameProgram->getProgramID() + "' for tlLogic '" + myTLSEditorParent->myEditedDef->getID() + "'");
1342  }
1343  } else {
1344  myTLSEditorParent->getViewNet()->setStatusBarText("No programs found for traffic light '" + myTLSEditorParent->myEditedDef->getID() + "'");
1345  }
1346 
1347  // clean up temporary container to avoid deletion of defs when it's destruct is called
1348  for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
1349  tmpTLLCont.removeProgram(def->getID(), def->getProgramID(), false);
1350  }
1351 
1352  myTLSEditorParent->myTLSPhases->initPhaseTable();
1353  myTLSEditorParent->myTLSModifications->setHaveModifications(true);
1354  }
1355  return 0;
1356 }
1357 
1358 
1359 long
1361  FXString file = MFXUtils::getFilename2Write(this,
1362  "Save TLS Program as", ".xml",
1364  gCurrentFolder);
1365  if (file == "") {
1366  return 1;
1367  }
1368  OutputDevice& device = OutputDevice::getDevice(file.text());
1369 
1370  // save program
1371  device.writeXMLHeader("additional", "additional_file.xsd");
1372  device.openTag(SUMO_TAG_TLLOGIC);
1373  device.writeAttr(SUMO_ATTR_ID, myTLSEditorParent->myEditedDef->getLogic()->getID());
1374  device.writeAttr(SUMO_ATTR_TYPE, myTLSEditorParent->myEditedDef->getLogic()->getType());
1375  device.writeAttr(SUMO_ATTR_PROGRAMID, myTLSEditorParent->myEditedDef->getLogic()->getProgramID());
1376  device.writeAttr(SUMO_ATTR_OFFSET, writeSUMOTime(myTLSEditorParent->myEditedDef->getLogic()->getOffset()));
1377  // write the phases
1378  const bool varPhaseLength = myTLSEditorParent->myEditedDef->getLogic()->getType() != TrafficLightType::STATIC;
1379  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
1380  for (auto j : phases) {
1381  device.openTag(SUMO_TAG_PHASE);
1382  device.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(j.duration));
1383  device.writeAttr(SUMO_ATTR_STATE, j.state);
1384  if (varPhaseLength) {
1386  device.writeAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(j.minDur));
1387  }
1389  device.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(j.maxDur));
1390  }
1391  }
1392  device.closeTag();
1393  }
1394  device.close();
1395  return 1;
1396 }
1397 
1398 
1399 std::string
1401  double time = STEPS2TIME(steps);
1402  if (time == std::floor(time)) {
1403  return toString(int(time));
1404  } else {
1405  return toString(time);
1406  }
1407 }
1408 
1409 long
1410 GNETLSEditorFrame::TLSFile::onUpdNeedsDef(FXObject* o, FXSelector, void*) {
1411  const bool enable = myTLSEditorParent->myTLSAttributes->getNumberOfTLSDefinitions() > 0;
1412  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
1413  return 1;
1414 }
1415 
1416 
1417 /****************************************************************************/
int NUM_POINTS
FXDEFMAP(GNETLSEditorFrame) GNETLSEditorFrameMap[]
@ MID_GNE_TLSFRAME_SUBRENAME
sub-rename TLS
Definition: GUIAppEnum.h:875
@ MID_GNE_TLSFRAME_PHASE_CREATE
create phase thable
Definition: GUIAppEnum.h:881
@ MID_CANCEL
Cancel-button pressed.
Definition: GUIAppEnum.h:247
@ MID_GNE_TLSFRAME_ADDOFF
add off to TLS
Definition: GUIAppEnum.h:877
@ MID_GNE_TLSFRAME_SAVE_PROGRAM
cleanup unused states
Definition: GUIAppEnum.h:897
@ MID_GNE_TLSFRAME_GUESSPROGRAM
replace program with a newly guessed program
Definition: GUIAppEnum.h:863
@ MID_GNE_TLSFRAME_GROUP_STATES
group states
Definition: GUIAppEnum.h:891
@ MID_GNE_TLSFRAME_PHASE_DELETE
delete phase thable
Definition: GUIAppEnum.h:883
@ MID_GNE_TLSFRAME_CREATE
Create TLS.
Definition: GUIAppEnum.h:869
@ MID_GNE_TLSFRAME_ADDUNUSED
add unused states
Definition: GUIAppEnum.h:889
@ MID_OK
Ok-button pressed.
Definition: GUIAppEnum.h:245
@ MID_GNE_TLSFRAME_SWITCH
switch between programs
Definition: GUIAppEnum.h:867
@ MID_GNE_TLSFRAME_SELECT_JUNCTION
selected junction von TLS
Definition: GUIAppEnum.h:859
@ MID_GNE_TLSFRAME_OFFSET
definition related controls
Definition: GUIAppEnum.h:865
@ MID_GNE_TLSFRAME_CLEANUP
cleanup unused states
Definition: GUIAppEnum.h:885
@ MID_GNE_TLSFRAME_LOAD_PROGRAM
Load Program.
Definition: GUIAppEnum.h:895
@ MID_GNE_TLSFRAME_UNGROUP_STATES
ungroup states
Definition: GUIAppEnum.h:893
@ MID_GNE_TLSFRAME_RENAME
rename TLS
Definition: GUIAppEnum.h:873
@ MID_GNE_TLSFRAME_PHASE_TABLE
select phase thable
Definition: GUIAppEnum.h:879
@ MID_GNE_TLSFRAME_DELETE
delete TLS
Definition: GUIAppEnum.h:871
#define GUIDesignLabelLeft
Definition: GUIDesigns.h:175
#define GUIDesignButton
Definition: GUIDesigns.h:62
#define GUIDesignComboBoxAttribute
Combo box static (cannot be edited) extended over the matrix column.
Definition: GUIDesigns.h:246
#define GUIDesignComboBoxNCol
number of column of every combo box
Definition: GUIDesigns.h:255
#define GUIDesignTextField
Definition: GUIDesigns.h:36
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition: GUIDesigns.h:313
#define GUIDesignLabelAttribute
label extended over the matrix column with thick frame
Definition: GUIDesigns.h:199
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition: GUIDesigns.h:54
#define GUIDesignGroupBoxFrame
Group box design extended over frame.
Definition: GUIDesigns.h:278
#define GUIDesignTableLimitedHeight
design for table extended over frame but with limited Height
Definition: GUIDesigns.h:523
FXString gCurrentFolder
The folder used as last.
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:286
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:278
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:276
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:31
@ SUMO_TAG_PHASE
a single phase description
@ SUMO_TAG_TLLOGIC
a traffic light logic
@ SUMO_TAG_JUNCTION
begin/end of the description of a junction
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_TL_YELLOW_MAJOR
The link has yellow light, may pass.
@ LINKSTATE_TL_GREEN_MAJOR
The link has green light, may pass.
@ LINKSTATE_DEADEND
This is a dead end link.
@ LINKSTATE_TL_YELLOW_MINOR
The link has yellow light, has to brake anyway.
@ LINKSTATE_TL_RED
The link has red light (must brake)
@ LINKSTATE_TL_GREEN_MINOR
The link has green light, has to brake.
@ SUMO_ATTR_OFFSET
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_ID
@ SUMO_ATTR_MAXDURATION
maximum duration of a phase
@ SUMO_ATTR_PROGRAMID
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_MINDURATION
@ SUMO_ATTR_STATE
The state of a link.
T MIN2(T a, T b)
Definition: StdDefs.h:73
T MAX2(T a, T b)
Definition: StdDefs.h:79
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
static bool canParse(const std::string &string)
true if a value of type T can be parsed from string
GNENet * getNet() const
get pointer to net
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:49
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition: GNEEdge.cpp:723
GNEViewNet * myViewNet
View Net.
Definition: GNEFrame.h:113
FXVerticalFrame * myContentFrame
Vertical frame that holds all widgets of frame.
Definition: GNEFrame.h:116
virtual void show()
show Frame
Definition: GNEFrame.cpp:108
void showOverlappedInspection(const GNEViewNetHelper::ObjectsUnderCursor &objectsUnderCursor, const Position &clickedPosition)
show template editor
int getNumberOfOverlappedACs() const
get number of overlapped ACSs
void hideOverlappedInspection()
hide template editor
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
LinkState getLinkState() const
whether link state has been modfied
int getTLIndex() const
get Traffic Light index
const std::vector< GNEEdge * > & getGNEIncomingEdges() const
Returns incoming GNEEdges.
std::string getAttribute(SumoXMLAttr key) const
void selectTLS(bool selected)
notify the junction of being selected in tls-mode. (used to control drawing)
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
const std::vector< GNEEdge * > & getGNEOutgoingEdges() const
Returns incoming GNEEdges.
NBNode * getNBNode() const
Return net build node.
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:45
GNEEdge * getParentEdge() const
get arent edge
Definition: GNELane.cpp:111
SUMORTree & getGrid()
Returns the RTree used for visualisation speed-up.
Definition: GNENet.cpp:149
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition: GNENet.cpp:2282
std::vector< GNELane * > retrieveLanes(bool onlySelected=false)
return all lanes
Definition: GNENet.cpp:1322
void computeJunction(GNEJunction *junction)
trigger recomputation of junction shape and logic param[in] window The window to inform about delay
Definition: GNENet.cpp:1691
std::vector< GNEEdge * > retrieveEdges(bool onlySelected=false)
return all edges
Definition: GNENet.cpp:1249
NBEdgeCont & getEdgeCont()
returns the NBEdgeCont of the underlying netbuilder
Definition: GNENet.cpp:2288
GNEJunction * retrieveJunction(const std::string &id, bool failHard=true) const
get junction by id
Definition: GNENet.cpp:1113
void initTLSAttributes(GNEJunction *junction)
initializes the definitions and corresponding listbox
FXLabel * myProgramLabel
program label
FXTextField * myOffsetTextField
the control for modifying offset
int getNumberOfPrograms() const
get number of programs
SUMOTime getOffset() const
get current offset in SUMOTIme
void setOffset(SUMOTime offset)
set new offset
void clearTLSAttributes()
clear TLS attributes
FXComboBox * myProgramComboBox
the comboBox for selecting the tl-definition to edit
int getNumberOfTLSDefinitions() const
get number of definitions
TLSAttributes(GNETLSEditorFrame *TLSEditorParent)
constructor
NBTrafficLightDefinition * getCurrentTLSDefinition() const
get current definition
FXTextField * myNameTextField
name text field
FXLabel * myOffsetLabel
offset label
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditorParent
FXButton * myNewTLProgram
button for create new Traffic light program
FXButton * myDeleteTLProgram
button for delete traffic light program
TLSDefinition(GNETLSEditorFrame *TLSEditorParent)
constructor
FXButton * mySaveTLSProgramButton
button for save TLS Programs
FXButton * myLoadTLSProgramButton
button for load TLS Programs
long onCmdLoadTLSProgram(FXObject *, FXSelector, void *)
TLSFile(GNETLSEditorFrame *TLSEditorParent)
FOX-declaration.
std::string writeSUMOTime(SUMOTime steps)
convert SUMOTime into string
long onCmdSaveTLSProgram(FXObject *, FXSelector, void *)
save TLS Programm to an additional file
long onUpdNeedsDef(FXObject *, FXSelector, void *)
enable buttons, only when a tlLogic is being edited
FXLabel * myLabelJunctionID
label for junction ID
FXTextField * myTextFieldJunctionID
text field for junction ID
GNEJunction * getCurrentJunction() const
get current modified junction
void setCurrentJunction(GNEJunction *junction)
set current junction
void updateJunctionDescription() const
update descrition
TLSJunction(GNETLSEditorFrame *tlsEditorParent)
constructor
TLSModifications(GNETLSEditorFrame *TLSEditorParent)
constructor
void setHaveModifications(bool value)
set if current TLS was modified
FXButton * myDiscardModificationsButtons
button for cancel modifications
bool checkHaveModifications() const
check if current TLS was modified
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditor Parent
FXButton * mySaveModificationsButtons
button for save modifications
FXScrollWindow * myTableScroll
window for oversized phase tables
FXLabel * myCycleDuration
label with the cycle duration
void showCycleDuration()
show cycle duration
FXButton * myDeleteSelectedPhaseButton
delete phase button
FXFont * myTableFont
font for the phase table
FXButton * myInsertDuplicateButton
insert new phase button
TLSPhases(GNETLSEditorFrame *TLSEditorParent)
constructor
FXTable * myPhaseTable
table for selecting and rearranging phases and for changing duration
FXTable * getPhaseTable() const
get phase table
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditor Parent
void updateCycleDuration()
recomputes cycle duration and updates label
void initPhaseTable(int index=0)
initialies the phase table
void hideCycleDuration()
hide cycle duration
const std::vector< NBTrafficLightLogic::PhaseDefinition > & getPhases()
the phase of the current traffic light
long onCmdOK(FXObject *, FXSelector, void *)
void handleChange(GNEInternalLane *lane)
update phase definition for the current traffic light and phase
long onCmdGuess(FXObject *, FXSelector, void *)
Called when the user presses the button Guess.
void buildInternalLanes(NBTrafficLightDefinition *tlDef)
builds internal lanes for the given tlDef
GNETLSEditorFrame::TLSAttributes * myTLSAttributes
modul for TLS attributes
static std::string varDurString(SUMOTime dur)
convert duration (potentially undefined) to string
long onCmdDefCreate(FXObject *, FXSelector, void *)
Called when the user creates a TLS.
long onCmdDefAddOff(FXObject *, FXSelector, void *)
Called when the user adds a OFF.
long onCmdDefDelete(FXObject *, FXSelector, void *)
Called when the user deletes a TLS.
bool isTLSSaved()
check if modifications in TLS was saved
void editJunction(GNEJunction *junction)
edits the traffic light for the given junction
GNEFrameModuls::OverlappedInspection * myOverlappedInspection
Overlapped Inspection.
GNETLSEditorFrame::TLSModifications * myTLSModifications
modul for load/Save TLS Modifications
long onCmdPhaseEdit(FXObject *, FXSelector, void *)
Called when the user edits a Phase.
long onUpdDefCreate(FXObject *, FXSelector, void *)
Called when occurs an update of create definition.
GNETLSEditorFrame::TLSPhases * myTLSPhases
modul for TLS Phases
void selectedOverlappedElement(GNEAttributeCarrier *AC)
open AttributesCreator extended dialog (can be reimplemented in frame children)
long onCmdDefOffset(FXObject *, FXSelector, void *)
Called when the user changes the offset of a TLS.
TLIndexMap myInternalLanes
long onUpdNeedsSingleDef(FXObject *, FXSelector, void *)
Called to buttons that modify link indices.
bool parseTLSPrograms(const std::string &file)
parse TLS Programs from a file
bool controlsEdge(GNEEdge *edge) const
whether the given edge is controlled by the currently edited tlDef
long onCmdDefSubRename(FXObject *, FXSelector, void *)
Called when the user sub-renames a TLS.
long onUpdUngroupStates(FXObject *, FXSelector, void *)
Called to update the ungroups states button.
long onCmdPhaseDelete(FXObject *, FXSelector, void *)
Called when the user deletes a Phase.
long onCmdCancel(FXObject *, FXSelector, void *)
Called when the user presses the Cancel-button.
long onUpdModified(FXObject *, FXSelector, void *)
Called when occurs an update of modified.
static SUMOTime getSUMOTime(const FXString &string)
converts to SUMOTime
void handleMultiChange(GNELane *lane, FXObject *obj, FXSelector sel, void *data)
update phase definition for the current traffic light and phase
long onCmdDefRename(FXObject *, FXSelector, void *)
Called when the user renames a TLS.
long onUpdNeedsDef(FXObject *, FXSelector, void *)
Called when occurs an update of needs definition.
long onUpdNeedsDefAndPhase(FXObject *, FXSelector, void *)
Called when occurs an update of needs definition an dphase.
long onCmdUngroupStates(FXObject *, FXSelector, void *)
Called when the user ungroups states.
~GNETLSEditorFrame()
Destructor.
long onCmdGroupStates(FXObject *, FXSelector, void *)
Called when the user groups states.
NBLoadedSUMOTLDef * myEditedDef
the traffic light definition being edited
long onUpdDefSwitch(FXObject *, FXSelector, void *)
Called when occurs an update of switch definition.
long onCmdPhaseCreate(FXObject *, FXSelector, void *)
Called when the user creates a Phase.
GNETLSEditorFrame::TLSJunction * myTLSJunction
modul for TLS Junction
bool fixedDuration() const
whether the current traffic light uses fixed phase durations
void editTLS(const Position &clickedPosition, const GNEViewNetHelper::ObjectsUnderCursor &objectsUnderCursor)
edits the traffic light for the given clicked junction
long onCmdPhaseSwitch(FXObject *, FXSelector, void *)
Called when the user switchs a Phase.
void cleanup()
cleans up previous lanes
long onCmdAddUnused(FXObject *, FXSelector, void *)
Called when the user cleans up states.
long onCmdDefSwitch(FXObject *, FXSelector, void *)
Called when the user switchs a TLS.
void show()
show inspector frame
long onCmdCleanup(FXObject *, FXSelector, void *)
Called when the user cleans up states.
void p_begin(const std::string &description)
Begin undo command sub-group. This begins a new group of commands that are treated as a single comman...
Definition: GNEUndoList.cpp:71
void p_end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
Definition: GNEUndoList.cpp:78
void p_abort()
reverts and discards ALL active command groups
class used to group all variables related with objects under cursor after a click over view
GNEJunction * getJunctionFront() const
get front junction or a pointer to nullptr
GNENet * getNet() const
get the net object
bool changeAllPhases() const
change all phases
Definition: GNEViewNet.cpp:593
GNEUndoList * getUndoList() const
get the undoList object
void updateViewNet() const
Mark the entire GNEViewNet to be repainted later.
Definition: GNEViewNet.cpp:318
void setStatusBarText(const std::string &text)
set staturBar text
Definition: GNEViewNet.cpp:575
virtual const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
static FXString getFilename2Write(FXWindow *parent, const FXString &header, const FXString &extension, FXIcon *icon, FXString &currentFolder)
Returns the file name to write.
Definition: MFXUtils.cpp:82
A loaded (complete) traffic light logic.
bool usingSignalGroups() const
whether this definition uses signal group (multiple connections with the same link index)
void ungroupSignals()
let all connections use a distinct link index
void groupSignals()
let connections with the same state use the same link index
NBTrafficLightLogic * getLogic()
Returns the internal logic.
void setOffset(SUMOTime offset)
Sets the offset of this tls.
A definition of a pedestrian crossing.
Definition: NBNode.h:129
Represents a single node (junction) during network building.
Definition: NBNode.h:66
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node)
Definition: NBNode.h:322
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:317
The base class for traffic light logic definitions.
const NBConnectionVector & getControlledLinks() const
returns the controlled links (depends on previous call to collectLinks)
const std::string & getProgramID() const
Returns the ProgramID.
TrafficLightType getType() const
get the algorithm type (static etc..)
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
int computeBrakingTime(double minDecel) const
Computes the time vehicles may need to brake.
NBTrafficLightLogic * compute(OptionsCont &oc)
Computes the traffic light logic.
virtual void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
static const SUMOTime UNSPECIFIED_DURATION
The definition of a single phase of the logic.
std::string state
The state definition.
std::string name
option phase name
SUMOTime duration
The duration of the phase in s.
std::vector< int > next
next phase indices or empty list
A container for traffic light definitions and built programs.
bool removeProgram(const std::string id, const std::string programID, bool del=true)
Removes a program of a logic definition from the dictionary.
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
NBTrafficLightLogic * getLogic(const std::string &id, const std::string &programID) const
Returns the computed logic for the given name.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
A SUMO-compliant built logic for a traffic light.
void setPhaseMinDuration(int phaseIndex, SUMOTime duration)
SUMOTime getOffset() const
Returns the offset of first switch.
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
void setPhaseName(int phaseIndex, const std::string &name)
void setPhaseDuration(int phaseIndex, SUMOTime duration)
Modifies the duration for an existing phase (used by NETEDIT)
void setPhaseState(int phaseIndex, int tlIndex, LinkState linkState)
Modifies the state for an existing phase (used by NETEDIT)
void setPhaseMaxDuration(int phaseIndex, SUMOTime duration)
int getNumLinks()
Returns the number of participating links.
void addStep(SUMOTime duration, const std::string &state, const std::vector< int > &next=std::vector< int >(), const std::string &name="", int index=-1)
Adds a phase to the logic.
void setPhaseNext(int phaseIndex, const std::vector< int > &next)
void setStateLength(int numLinks, LinkState fill=LINKSTATE_TL_RED)
Importer for edge connections stored in XML.
const std::string & getID() const
Returns the id.
Definition: Named.h:73
A storage for options typed value containers)
Definition: OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:60
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
void close()
Closes the device and removes it from the dictionary.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:239
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:36
A list of positions.
double length() const
Returns the length.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
PositionVector reverse() const
reverse position vector
void removeAdditionalGLObject(GUIGlObject *o)
Removes an additional object (detector/shape/trigger) from being visualised.
Definition: SUMORTree.h:154
void addAdditionalGLObject(GUIGlObject *o)
Adds an additional object (detector/shape/trigger) for visualisation.
Definition: SUMORTree.h:124
static std::string prune(const std::string &str)
Removes trailing and leading whitechars.
Definition: StringUtils.cpp:47
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:148
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:188