Welcome to RichStrat, currently showcasing the planets with orbits shown to scale. The other pages use a number of different types of maps.

All the code is written in Scala. When displayed on the web this scala code is compiled to Javascript. However all the demonstations will also compile to Java byte code and work on the JavaFx graphical platfrom. I hope with my modest computing skills to demonstate the power and enjoyment of using Scala for simple games and every day adminstration of personal and small business tasks. At least for the time being I'm not going to give a full introduction to Scala, there are a number of good resources out there, but before I present any code I just want to draw attention to the four common basic types that I use in Scala coding and from which most other types are created.

Note that 7 is an Int. but "7" is a String. -8.22 is a Double, but "-8.22" is a String and false is a Boolean, but "false" is a String. I know this may sound a bit dry, a bit abstract, a bit boring even, but if you can grasp the above you really have cracked the foundations of computer programming. Which is a wonderful thing because now you can get computers to start working for you.

Petyr Baelish, Game of Thrones: When the Queen proclaims one king and the Hand proclaims another, whose peace do the Computers protect? Who do they follow? The man who programmes them.

Languages like Basic which you may have come across try to hide these concepts from you, but this leads to no end of trouble down the road for a small time saving at the begining which is why Scala is a way better language than Basic and its ilk. So here's my Vec2 class file. This is the foundation of the map algorithorithms. Note how it contains two data elements, two Doubles, two decimal values.

    
package pUtil
import math._

/** A 2 dimensional vector, can be used to represent 2 dimensional points and translations of 2 dimensional points */
class Vec2 (xI: Double, yI: Double) extends Persist1
{
   val x: Double = xI
   val y: Double = yI
   override def equals(other: Any): Boolean = other match
   {
      case Vec2(px, py) => (x =\ px) && (y =\ py)
      case _ => false
   }
   override def toString = "x: " + x.toString + ", y: " + y   
   def toPair: (Double, Double) = (x, y)
   def +(other: Vec2): Vec2 = Vec2(x + other.x, y + other.y)
   def addXY (otherX: Double, otherY: Double): Vec2 = Vec2(x + otherX, y + otherY)
   def -(other: Vec2): Vec2 = Vec2(x - other.x, y - other.y)
   def unary_- : Vec2 = Vec2(-x, -y)
   def *(factor: Double): Vec2 = Vec2(x * factor, y * factor)
   def /(divisor: Double): Vec2 = Vec2(x / divisor, y / divisor)
   def addX(adj: Double): Vec2 = Vec2(x + adj, y)
   def addY(adj: Double): Vec2 = Vec2(x, y + adj)
   def subX(adj: Double): Vec2 = Vec2(x - adj, y)   
   def subY(adj: Double): Vec2 = Vec2(x, y - adj)
   override def persistValues: Seq[String] = Seq(x.toString, y.toString)
   override def persistName: String = "Vec2"
   //def persSemi: String = x.toString() -+ y.toString
   /* Reverses the y coordinate. Useful for translating between canvases where the y axis measures down and coordinate systems where y is up */
   def reverseY: Vec2 = Vec2(x, -y)
   def distanceFrom(other: Vec2): Double = math.sqrt({val dim = (x - other.x); dim * dim} + {val dim = (y - other.y); dim * dim})
   def rectVerts(width: Double, height: Double): Seq[Vec2] =
   {
      val ax = width / 2
      val ay = height / 2
      Seq(Vec2(x - ax, y + ay), Vec2(x + ax, y + ay),Vec2(x + ax, y -ay), Vec2(x -ax, y -ay))
   }
   def withinRect(target: Vec2, width: Double, height: Double): Boolean =
   {
      val xd: Double = width / 2
      val yd: Double = height / 2
      (x > target.x - xd) && (x < target.x + xd) && (y > target.y - yd) && (y < target.y + yd)
   }
   //def rotate(ang: Double): Vec2 = ang 
   def rotate(angle: Angle): Vec2 = angle.value match
   {
     case 0 => Vec2.this
     case a => Vec2(x * cos(a) - y * sin(a), x * sin(a) + y * cos(a))
   }
  
   def trans(aff: AffD2): Vec2 = aff(this) 
}

object Vec2
{
   def apply(x: Double, y: Double): Vec2 = new Vec2(x, y)
   def unapply(orig: Vec2): Option[(Double, Double)] = Some((orig.x, orig.y))   
   def zero: Vec2 = new Vec2(0, 0)
   def circlePt(angle: Double): Vec2 = Vec2(cos(angle), sin(angle))
   def circlePtClockwise(angle: Double): Vec2 = Vec2(cos(angle), - sin(angle))
   def gets(coods: Double *): Array[Vec2] =
   {
      (for ( i <- 0 until coods.length / 2) yield Vec2(coods(i * 2), coods(i * 2 + 1))).toArray
   }
   def rectBL(left: Double, bottom: Double, width: Double, height: Double): Array[Vec2] =
      Array[Vec2](Vec2(left, bottom), Vec2(left, bottom + height), Vec2(left + width, bottom + height), Vec2(left + width, bottom))
   def squareBL(left: Double, bottom: Double, length: Double): Array[Vec2] =
      Array[Vec2](Vec2(left, bottom), Vec2(left, bottom + length), Vec2(left + length, bottom + length), Vec2(left + length, bottom))   
   
   implicit class ImpVec2Array(arr: Array[Vec2])
   {
      def +++ (offset: Vec2): Array[Vec2] = arr.map(_ + offset)
      def xy_+ (xOff: Double, yOff: Double): Array[Vec2] = arr.map(orig => Vec2(orig.x + xOff, orig.y + yOff))
      def --- (offset: Vec2): Array[Vec2] = arr.map(_ - offset)
      def *** (factor: Double): Array[Vec2] = arr.map(_ * factor)
      def a_*+ (factor: Double, offset: Vec2): Array[Vec2] = arr.map(_ * factor + offset)
      def a_+* (offset: Vec2, factor: Double): Array[Vec2] = arr.map(i => (i + offset) * factor)
      def xy_*+ (factor: Double, xOff: Double, yOff: Double): Array[Vec2] = arr.map(_ * factor + Vec2(xOff, yOff))
      def a_+* (xOff: Double, yOff: Double, factor: Double): Array[Vec2] = arr.map(i => (i + Vec2(xOff, yOff)) * factor)
   }
   
   import scala.collection.mutable.{ Builder }
   import scala.collection._
   
   
   implicit class ImpVec2Traversible[Repr](travLike: TraversableLike[Vec2, Repr])
   {
      def +++ (offset: Vec2)(implicit bf: generic.CanBuildFrom[Repr, Vec2, Repr]): Repr =
      {
         def builder =
         { // extracted to keep method size under 35 bytes, so that it can be JIT-inlined
            val b = bf(travLike.repr)
            b.sizeHint(travLike)
            b
         }
         val b = builder
         for (x <- travLike) b += x + offset
         b.result
      }
      def xy_+ (xOff: Double, yOff: Double)(implicit bf: generic.CanBuildFrom[Repr, Vec2, Repr]): Repr =
      {
         def builder =
         { // extracted to keep method size under 35 bytes, so that it can be JIT-inlined
            val b = bf(travLike.repr)
            b.sizeHint(travLike)
            b
         }
         val b = builder
         for (orig <- travLike) b += Vec2(orig.x + xOff, orig.y + yOff)
         b.result
      }
      
      def --- (offset: Vec2)(implicit bf: generic.CanBuildFrom[Repr, Vec2, Repr]): Repr =
      {
         def builder =
         { // extracted to keep method size under 35 bytes, so that it can be JIT-inlined
            val b = bf(travLike.repr)
            b.sizeHint(travLike)
            b
         }
         val b = builder
         for (x <- travLike) b += x - offset
         b.result
      }
      
      def *** (factor: Double)(implicit bf: generic.CanBuildFrom[Repr, Vec2, Repr]): Repr =
      {
         def builder =
         { // extracted to keep method size under 35 bytes, so that it can be JIT-inlined
            val b = bf(travLike.repr)
            b.sizeHint(travLike)
            b
         }
         val b = builder
         for (x <- travLike) b += x * factor
         b.result
      }
      
      def a_*+ (factor: Double, offset: Vec2)(implicit bf: generic.CanBuildFrom[Repr, Vec2, Repr]): Repr =
      {
         def builder =
         { // extracted to keep method size under 35 bytes, so that it can be JIT-inlined
            val b = bf(travLike.repr)
            b.sizeHint(travLike)
            b
         }
         val b = builder
         for (x <- travLike) b += x * factor + offset
         b.result
      }
      def a_+* (offset: Vec2, factor: Double)(implicit bf: generic.CanBuildFrom[Repr, Vec2, Repr]): Repr =
      {
         def builder =
         { // extracted to keep method size under 35 bytes, so that it can be JIT-inlined
            val b = bf(travLike.repr)
            b.sizeHint(travLike)
            b
         }
         val b = builder
         for (x <- travLike) b += (x + offset) * factor
         b.result
      }      
   }
   
   
//   def pntInPolygon(verts: Seq[Vec2], pt: Vec2): Boolean = 
//   { //Checks whether a forward horrisontal ray crosses this polygn side      
//      val rayIntersections: Seq[Line2] = Line2.SeqFromPts(verts).filter(ls => 
//         //Checks whether a forward horrisontal ray crosses this polygn side
//         if ( 
//                //Check if point is above or below the polygon side
//            ((pt.y > ls.y1) && (pt.y > ls.y2)) || //above pnt1 and pnt2
//            ((pt.y < ls.y1) && (pt.y < ls.y2)) //below pnt1 and pnt 2
//          ) false
//          else 
//          {             
//             val deltaY = ls.y2 - ls.y1
//             if (0.000001 > deltaY.abs) false //if the polygon side is close to horrisontal the
//// point is close enough to the perimiter of the polygon that the point can measured as outside
//             else
//             {                
//                val ptDeltaY = pt.y - ls.y1
//                val deltaX = ls.x2 - ls.x1
//                val lineX = ls.x1 + (deltaX * ptDeltaY / deltaY)
//                pt.x > lineX
//             }
//          })        
//   rayIntersections.length.isOdd //For a convex polygon the ray can only cross one side if inside
//}
}