TerrainRangeArc::TerrainRangeArc(const Arc2d & data, AxisType width) { const Point2d vec = data.start - data.center; const AxisType radii = vec.GetLength(); const AxisType radiiMax = radii + width / 2; const AxisType radiiMin = (width / 2 < radii) ? radii - width / 2 : 0; const int iMin = utils::FloatFloorToInt(-radiiMax); const int iMax = utils::FloatCeilToInt(radiiMax); const int iRadiiMin = utils::FloatFloorToInt(radiiMin); for (int i = iMin; i <= iMax; ++i) { const AxisType xMax = GetXShift(i, iMax); if (std::abs(i) >= iRadiiMin) { ProcessRange(vec, data.angle, i, AxisPairType(-xMax, xMax), data.center); } else { const AxisType xMin = GetXShift(i, iRadiiMin); const int lxMin = utils::FloatCeilToInt(-xMin); const int rxMin = utils::FloatFloorToInt(xMin); if (lxMin == rxMin) { ProcessRange(vec, data.angle, i, AxisPairType(-xMax, xMax), data.center); } else { ProcessRange(vec, data.angle, i, AxisPairType(-xMax, (float)lxMin), data.center); ProcessRange(vec, data.angle, i, AxisPairType((float)rxMin, xMax), data.center); } } } }
void RailRoadSplitter::Visit(RailRoadArc & rra) { RailRoadParametersTaker rrpt; rra.Accept(rrpt); const Point3d start = rrpt.GetStart(); const Point2d start2d = Point2d::Cast(start); const Point3d & end = rrpt.GetEnd(); const Point2d & center = rra.GetCenter(); const float zShift = rra.GetZShift(); const Rotation rotation = utils::GetAngleRotation(rra.GetAngle()); const Angle absAngle = utils::GetAngleAbs(rra.GetAngle()); const Point2d shiftedStart = start2d - center; const float radiiFromStart = shiftedStart.GetLength(); using SortedPointsMap = std::map<Angle, Point3d>; SortedPointsMap sortedPoints; boost::for_each(splitPoints_, [&](Point3d p) { if (start == p || end == p) { return; } const Point2d shiftedSplit = Point2d::Cast(p) - center; const float radiiFromSplit = shiftedSplit.GetLength(); // ignore split point not on the arc if (!utils::CheckNear(radiiFromSplit, radiiFromStart, 0.0001f)) { return; } const Angle angleToSplit = utils::GetRotationAngle360(shiftedStart, shiftedSplit, rotation); if (angleToSplit > absAngle) { return; } p.z() = start.z() + zShift * angleToSplit / absAngle; sortedPoints.emplace(angleToSplit, p); }); // if no points did a split, then nothing to return // ignore points not on the arc and points outside of the arc if (sortedPoints.empty()) { return; } sortedPoints.emplace(absAngle, end); Angle prevAngle; Point3d startPoint = start; boost::for_each(sortedPoints, [&](const SortedPointsMap::value_type & v) { spitResult_.push_back(RailRoadFactory::Arc(startPoint, utils::GetAdjustedAngleByRotation(v.first - prevAngle, rotation), rra.GetCenter(), v.second.z() - startPoint.z())); startPoint = v.second; prevAngle = v.first; }); }