Guest User

Untitled

a guest
Feb 18th, 2018
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.90 KB | None | 0 0
  1. class CSquareSerializer extends CSquareHelpers {
  2. case class RelativePoint(val x: Int, val y: Int)
  3. implicit def tuple2relpoint(t: (Int, Int)) = RelativePoint(t._1, t._2)
  4.  
  5. sealed trait Component
  6. case class CoarseComponent(val q: Int) extends Component
  7. case class FineComponent(val q: Int, val x: Int, val y: Int) extends Component
  8. case class TopComponent(val q: Int, val x: Int, val y: Int) extends Component
  9.  
  10. def serialize(square: CSquare) = {
  11. val size = square.size
  12. val disp = square.displacement
  13.  
  14. val lastGranularity = round(10 * size / pow(10, round(log(size) / log(10.0)))) / 10.0
  15.  
  16. val normalizedSize = if (lastGranularity == 0.5) size / 5 else size
  17.  
  18. // compute list of square component sizes: e.g. [10, 1, 0.1, 0.01, 0.001])
  19. val sizes = from(-1).map(a => pow(10, -a)).takeWhile(_ >= normalizedSize)
  20.  
  21. val x = disp(0) / 10
  22. val y = disp(1) / 10
  23.  
  24. val decX = x - x.floor
  25. val decY = y - y.floor
  26.  
  27. // clear rounding issues
  28. def clean(x: Double) = round(x * 100000) / 100000.0
  29.  
  30. // create a stream of digits
  31. def digits(x: Double) = clean(x).toString.slice(2, 1 + sizes.size).map(_.toString.toInt).padTo(sizes.size - 1, 0)
  32.  
  33. def format(q: Component): String = q match {
  34. case CoarseComponent(q) => "%s".format(q)
  35. case FineComponent(q, x, y) => "%s%s%s".format(q, y, x)
  36. case TopComponent(q, x, y) => "%s%d%02d".format(q, y, x)
  37. }
  38.  
  39. // handle last quadrant when the final granularity is 0.5
  40. def smartQuadrantTuple(a: ((Int, Int), Int)): Component = smartQuadrant(a._1, a._2)
  41.  
  42. def smartQuadrant(relPoint: RelativePoint, n: Int): Component = {
  43. val q = quadrant(relPoint)
  44.  
  45. if ((lastGranularity == 0.5) && (n == sizes.size - 2))
  46. CoarseComponent(q.q)
  47. else
  48. q
  49. }
  50.  
  51. def quadrant(a: RelativePoint): FineComponent = a match {
  52. case RelativePoint(x, y) if x < 5 && y < 5 => FineComponent(1, x, y)
  53. case RelativePoint(x, y) if x >= 5 && y < 5 => FineComponent(2, x, y)
  54. case RelativePoint(x, y) if x < 5 && y >= 5 => FineComponent(3, x, y)
  55. case RelativePoint(x, y) if x >= 5 && y >= 5 => FineComponent(4, x, y)
  56. }
  57.  
  58. def topQuadrant = {
  59. val v = square.quadrant * DenseVector(1, 1)
  60. (v(0), v(1)) match {
  61. case (x, y) if x > 0 && y > 0 => 1
  62. case (x, y) if x > 0 && y < 0 => 3
  63. case (x, y) if x < 0 && y < 0 => 5
  64. case (x, y) if x < 0 && y > 0 => 7
  65. }
  66. }
  67.  
  68. // the first component is computed differently, using specifi codes for top level quadrants
  69. val topComponent = TopComponent(topQuadrant, floor(x).toInt, floor(y).toInt)
  70.  
  71. // the rest is more regular, we just have to stream the x,y digits
  72. // and generate code components for the subquadrant
  73. val rest = (digits(decX) zip digits(decY)).zipWithIndex.map(smartQuadrantTuple).toList
  74.  
  75. // and then glue the formatted components together
  76. (topComponent :: rest).map(format).mkString(":")
  77. }
  78. }
Add Comment
Please, Sign In to add comment