public override bool Equals(object obj) { if (obj is PrimitivePair <S, T> ) { PrimitivePair <S, T> other = obj as PrimitivePair <S, T>; return(first.Equals(other.first) && second.Equals(other.second)); } else { return(false); } }
virtual public List <PrimitiveTriple <float, float, float> > Generate(GridMath gridMath, Random rand) { // List to return List <PrimitiveTriple <float, float, float> > posList = new List <PrimitiveTriple <float, float, float> >(); // First determine the # of units int numUnits = (int)Math.Ceiling(numMean); if (numStdDev > 0) { numUnits = (int)Math.Round(RandN(numMean, numStdDev, (float)numMin, (float)numMax, rand)); } // For each unit PrimitivePair <float, float> tempPos = new PrimitivePair <float, float>(0, 0); PrimitivePair <float, float> anchor; PrimitivePair <int, int> tempGrid; bool laydownFound; for (int i = 0; i < numUnits; i++) { // Laydown not valid by default laydownFound = false; // Randomly pick an anchor (all anchors already in world coordinates) anchor = anchors[rand.Next(0, anchors.Count)]; // Note: rand.Next max value is exclusive // Keep trying points until we find one that satisfies grid constraints while (!laydownFound) { // Now independently pick X and Z deviations from that point tempPos.first = anchor.first + RandN(0.0f, fromAnchorStdDev_km, 0.0f, fromAnchorMax_km, rand); tempPos.second = anchor.second + RandN(0.0f, fromAnchorStdDev_km, 0.0f, fromAnchorMax_km, rand); // Convert that temp position to grid tempGrid = gridMath.WorldToGrid(tempPos); // Check to see if the grid is within allowed if (allowedCells.Contains(tempGrid)) { laydownFound = true; } } // Save the 3D point posList.Add(new PrimitiveTriple <float, float, float>(tempPos.first, 0, tempPos.second)); } // Return list of randomized positions return(posList); }
// Transforms a hex cell center (u,v) in grid coordinates to a point (x,z) in world coordinates // Based on reference: http://www.redblobgames.com/grids/hexagons/#hex-to-pixel public PrimitivePair <float, float> GridToWorld(PrimitivePair <int, int> gridCoordinate) { // Extract inputs int grid_u = gridCoordinate.first; int grid_v = gridCoordinate.second; // World x-coordinate float world_x = gridToWorldScale * (uHat_x * ((float)grid_u) + vHat_x * ((float)grid_v)) + gridOrigin_x; // World z-coordinate float world_z = gridToWorldScale * (uHat_z * ((float)grid_u) + vHat_z * ((float)grid_v)) + gridOrigin_z; // Package and return to caller return(new PrimitivePair <float, float>(world_x, world_z)); }
// Transforms a point (x,z) in world coordinates to the (u,v) of the hex cell that contains it // Based on references: http://www.redblobgames.com/grids/hexagons/#pixel-to-hex // http://www.redblobgames.com/grids/hexagons/#rounding public PrimitivePair <int, int> WorldToGrid(PrimitivePair <float, float> worldCoordinate) { // Extract inputs float world_x = worldCoordinate.first; float world_z = worldCoordinate.second; // Compute determinant of transform matrix for inverse float det = uHat_x * vHat_z - vHat_x * uHat_z; // Compute offsets from grid origin float rel_x = world_x - gridOrigin_x; float rel_z = world_z - gridOrigin_z; // Cube u-coordinate float cube_u = (vHat_z * rel_x - vHat_x * rel_z) / (gridToWorldScale * det); // Cube v-coordinate float cube_v = (-uHat_z * rel_x + uHat_x * rel_z) / (gridToWorldScale * det); // Cube w-coordinate float cube_w = -cube_u - cube_v; // Round cube coordinates to nearest integer float round_u = (float)Math.Round(cube_u); float round_v = (float)Math.Round(cube_v); float round_w = (float)Math.Round(cube_w); // Compute residual magnitudes float diff_u = Math.Abs(round_u - cube_u); float diff_v = Math.Abs(round_v - cube_v); float diff_w = Math.Abs(round_w - cube_w); // Snap to nearest hex center if (diff_u > diff_v && diff_u > diff_w) { round_u = -round_v - round_w; } else if (diff_v > diff_w) { round_v = -round_u - round_w; } // Cast to int to return to caller return(new PrimitivePair <int, int>((int)round_u, (int)round_v)); }