! * Wherever `A` and `B` cross, evaluates the exact x and y crossing position and * adds a point to `A` and `B`. * @pre `A.size() == B.size()` * @post `A.size() == B.size()` */
| 137 | * @post `A.size() == B.size()` |
| 138 | */ |
| 139 | void InsertCrossings( |
| 140 | std::vector<wxPoint2DDouble>& A, std::vector<wxPoint2DDouble>& B) |
| 141 | { |
| 142 | assert(A.size() == B.size()); |
| 143 | if (A.size() != B.size()) |
| 144 | return; |
| 145 | std::optional<bool> aWasBelow; |
| 146 | auto x0 = 0.; |
| 147 | auto y0_a = 0.; |
| 148 | auto y0_b = 0.; |
| 149 | auto it = A.begin(); |
| 150 | auto jt = B.begin(); |
| 151 | while (it != A.end()) |
| 152 | { |
| 153 | const auto x2 = it->m_x; |
| 154 | const auto y2_a = it->m_y; |
| 155 | const auto y2_b = jt->m_y; |
| 156 | const auto aIsBelow = y2_a < y2_b; |
| 157 | if (aWasBelow.has_value() && *aWasBelow != aIsBelow) |
| 158 | { |
| 159 | // clang-format off |
| 160 | // We have a crossing of y2_a and y2_b between x0 and x2. |
| 161 | // y_a(x) = y0_a + (x - x0) / (x2 - x0) * (y2_a - y0_a) |
| 162 | // and likewise for y_b. |
| 163 | // Let y_a(x1) = y_b(x1) and solve for x1: |
| 164 | // x1 = x0 + (x2 - x0) * (y0_b - y0_a) / ((a_n - y0_a) - (b_n - y0_b)) |
| 165 | // clang-format on |
| 166 | const auto x1 = |
| 167 | x0 + (x2 - x0) * (y0_a - y0_b) / (y2_b - y2_a + y0_a - y0_b); |
| 168 | const auto y = y0_a + (x1 - x0) / (x2 - x0) * (y2_a - y0_a); |
| 169 | if (std::isfinite(x1) && std::isfinite(y)) |
| 170 | { |
| 171 | it = A.emplace(it, x1, y)++; |
| 172 | jt = B.emplace(jt, x1, y)++; |
| 173 | }; |
| 174 | } |
| 175 | x0 = x2; |
| 176 | y0_a = y2_a; |
| 177 | y0_b = y2_b; |
| 178 | aWasBelow = aIsBelow; |
| 179 | ++it; |
| 180 | ++jt; |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | /*! |
| 185 | * Fills the area between the lines and the bottom of the panel with the given |