| Quintiq file version 2.0 | 
| #parent: #root | 
| Method DrawArcs | 
| { | 
|   Description: 'Draw the additional points between the start and the end point on each arc, so there are no overlapping positions.' | 
|   TextBody: | 
|   [* | 
|     program := LibOpt_Utility::ConstructMathematicalProgramWithoutAnalysis(); | 
|      | 
|     arcs := selectsortedset( this, UIGraphNode.Outgoing, arc, true, arc.First().X() ); | 
|     traverse( arcs, Elements, arc )  | 
|     { | 
|       var := program.NewContinuousVariable( LibOpt_UIGraphRow::VarY(), arc ); | 
|       var.LowerBound( 5.0 ); | 
|       var.UpperBound( Real::MaxReal() ); | 
|     } | 
|      | 
|     seen := construct( LibOpt_UIGraphArcs ); | 
|      | 
|     traverse( arcs, Elements, elem1 ) | 
|     { | 
|       dir1 := elem1.First().X() < elem1.Last().X(); | 
|       traverse( seen, Elements, elem2 )  | 
|       { | 
|         dir2 := elem2.First().X() < elem2.Last().X(); | 
|          | 
|         overlap_type := elem1.DetermineOverlap( elem2 ); | 
|          | 
|         if( dir1 = dir2 ) | 
|         { | 
|           if( ( dir1 and overlap_type = LibOpt_UIGraphArc::OverlapLeft() ) | 
|               or ( not dir1 and overlap_type = LibOpt_UIGraphArc::OverlapRight() ) ) | 
|           { | 
|             LibOpt_UIGraphRow::NewOverlapConstraint( program, elem1, elem2 ); | 
|           } | 
|           else if( ( dir1 and overlap_type = LibOpt_UIGraphArc::OverlapRight() ) | 
|               or ( not dir1 and overlap_type = LibOpt_UIGraphArc::OverlapLeft() ) ) | 
|           { | 
|             LibOpt_UIGraphRow::NewOverlapConstraint( program, elem2, elem1 ); | 
|           } | 
|           else if( overlap_type <> LibOpt_UIGraphArc::NoOverlap() ) | 
|           { | 
|             LibOpt_UIGraphRow::NewOverlapConstraint( program, elem1, elem2 ); | 
|           } | 
|         } | 
|         else if( overlap_type <> LibOpt_UIGraphArc::NoOverlap() ) | 
|         { | 
|           LibOpt_UIGraphRow::NewOverlapConstraint( program, elem1, elem2 ); | 
|         } | 
|       } | 
|       seen.Add( elem1 ); | 
|     } | 
|      | 
|     // Goal | 
|     traverse( arcs, Elements, arc )  | 
|     { | 
|       var := program.Variable( LibOpt_UIGraphRow::VarY(), arc ); | 
|       program.Goal().NewTerm( 1.0, var ); | 
|     } | 
|      | 
|     program.Execute(); | 
|      | 
|     max_value := max( arcs, Elements, arc, true, program.Variable( LibOpt_UIGraphRow::VarY(), arc ).OptimalValue() ); | 
|     text_offset := 13; | 
|     traverse( arcs, Elements, arc )  | 
|     { | 
|       var := program.Variable( LibOpt_UIGraphRow::VarY(), arc ); | 
|        | 
|       point := arc.First(); | 
|       point := point.To( arc.First().X(), [Real] this.UIGraph().Offset() + text_offset ) | 
|        | 
|       // Make the cut diagonally | 
|       mul := ifexpr( arc.First().X() > arc.Last().X(), -1, 1 ); | 
|       diff := abs( arc.First().X() - arc.Last().X() ); | 
|       diag_part_1 := minvalue( diff, var.OptimalValue() - this.UIGraph().Offset() ); | 
|       if( diag_part_1 > 0 ) | 
|       { | 
|         point := point.To( arc.First().X() + diag_part_1 * mul, var.OptimalValue() + text_offset ) | 
|       } | 
|        | 
|       // Make the cut diagonally again | 
|       diag_part_2 := minvalue( diff - diag_part_1, max_value - var.OptimalValue() ) | 
|       if( diag_part_2 > 0 ) | 
|       { | 
|         point := point.To( arc.Last().X() - diag_part_2 * mul, var.OptimalValue() + text_offset ) | 
|       } | 
|        | 
|       point := point.To( arc.Last().X(), max_value + text_offset ); | 
|       arc.Last().Y( max_value + 15 + text_offset ); | 
|     } | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |