├── .gitattributes ├── .gitignore ├── HexagonalGrids ├── .gitignore ├── .idea │ ├── .name │ ├── compiler.xml │ ├── copyright │ │ └── profiles_settings.xml │ ├── encodings.xml │ ├── gradle.xml │ ├── misc.xml │ ├── modules.xml │ ├── scopes │ │ └── scope_settings.xml │ └── vcs.xml ├── HexagonalGrids.iml ├── app │ ├── .gitignore │ ├── app.iml │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── net │ │ │ └── omplanet │ │ │ └── hexagonalgrids │ │ │ └── ApplicationTest.java │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── net │ │ │ └── omplanet │ │ │ └── hexagonalgrids │ │ │ ├── model │ │ │ ├── Cube.java │ │ │ ├── DemoObjects.java │ │ │ ├── Grid.java │ │ │ ├── Hex.java │ │ │ └── StorageMap.java │ │ │ └── ui │ │ │ ├── CircleImageView.java │ │ │ └── MainActivity.java │ │ └── res │ │ ├── drawable │ │ ├── empty_image.png │ │ ├── no_profile_image.png │ │ ├── profile1.png │ │ ├── profile10.png │ │ ├── profile11.png │ │ ├── profile12.png │ │ ├── profile13.png │ │ ├── profile14.png │ │ ├── profile15.png │ │ ├── profile2.png │ │ ├── profile3.png │ │ ├── profile4.png │ │ ├── profile5.png │ │ ├── profile6.png │ │ ├── profile7.png │ │ ├── profile8.png │ │ ├── profile9.png │ │ ├── ring.png │ │ ├── zoom_in.png │ │ └── zoom_out.png │ │ ├── layout │ │ ├── activity_main.xml │ │ └── hex_grid_layout.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── README.md └── Screenshots ├── Screenshot_2015-03-02-19-11-43.png ├── Screenshot_2015-03-02-19-11-49.png ├── Screenshot_2015-03-02-19-11-53.png ├── Screenshot_2015-03-02-19-11-56.png ├── Screenshot_2015-03-02-19-12-09.png ├── Screenshot_2015-03-02-19-13-57.png ├── Screenshot_2015-03-02-19-14-02.png ├── Screenshot_2015-03-02-19-14-11.png └── Screenshot_2015-03-02-19-14-22.png /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /HexagonalGrids/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | -------------------------------------------------------------------------------- /HexagonalGrids/.idea/.name: -------------------------------------------------------------------------------- 1 | Hexagonal Grids -------------------------------------------------------------------------------- /HexagonalGrids/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /HexagonalGrids/.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /HexagonalGrids/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HexagonalGrids/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /HexagonalGrids/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /HexagonalGrids/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /HexagonalGrids/.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /HexagonalGrids/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HexagonalGrids/HexagonalGrids.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /HexagonalGrids/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /HexagonalGrids/app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /HexagonalGrids/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | 7 | defaultConfig { 8 | applicationId "net.omplanet.hexagonalgrids" 9 | minSdkVersion 16 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile 'com.android.support:appcompat-v7:21.0.3' 25 | } 26 | -------------------------------------------------------------------------------- /HexagonalGrids/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Narek\Dev\android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/androidTest/java/net/omplanet/hexagonalgrids/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package net.omplanet.hexagonalgrids; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/java/net/omplanet/hexagonalgrids/model/Cube.java: -------------------------------------------------------------------------------- 1 | package net.omplanet.hexagonalgrids.model; 2 | 3 | /** 4 | * Cube using 3-vector for the coordinates (x, y, z) 5 | */ 6 | public class Cube { 7 | private int x; 8 | private int y; 9 | private int z; 10 | 11 | public Cube(int x, int y, int z) { 12 | this.x = x; 13 | this.y = y; 14 | this.z = z; 15 | } 16 | 17 | public Cube(float x, float y, float z) { 18 | int rx = Math.round(x); 19 | int ry = Math.round(y); 20 | int rz = Math.round(z); 21 | 22 | float x_diff = Math.abs(rx - x); 23 | float y_diff = Math.abs(ry - y); 24 | float z_diff = Math.abs(rz - z); 25 | 26 | if (x_diff > y_diff && x_diff > z_diff) 27 | rx = -ry-rz; 28 | else if (y_diff > z_diff) 29 | ry = -rx-rz; 30 | else 31 | rz = -rx-ry; 32 | 33 | this.x = rx; 34 | this.y = ry; 35 | this.z = rz; 36 | } 37 | 38 | public Hex toHex() { 39 | return new Hex(x, z); 40 | } 41 | 42 | public Hex cubeToOddRHex() { 43 | int q = x + (z - (z&1)) / 2; 44 | int r = z; 45 | 46 | return new Hex(q, r); 47 | } 48 | 49 | public String toString() { 50 | return x + ":" + y + ":" + z; 51 | } 52 | 53 | public int getX() { 54 | return x; 55 | } 56 | 57 | public void setX(int x) { 58 | this.x = x; 59 | } 60 | 61 | public int getZ() { 62 | return z; 63 | } 64 | 65 | public void setZ(int z) { 66 | this.z = z; 67 | } 68 | 69 | public int getY() { 70 | return y; 71 | } 72 | 73 | public void setY(int y) { 74 | this.y = y; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/java/net/omplanet/hexagonalgrids/model/DemoObjects.java: -------------------------------------------------------------------------------- 1 | package net.omplanet.hexagonalgrids.model; 2 | 3 | import net.omplanet.hexagonalgrids.R; 4 | 5 | /** 6 | * Demo contents. 7 | */ 8 | public class DemoObjects { 9 | //int size = mRadius*2+1; 10 | //squareMap = new Integer[size][size]; 11 | public static Object[][] squareMap = new Integer[][] { 12 | { 13 | R.drawable.profile1, 0, R.drawable.profile2, R.drawable.profile3}, 14 | {R.drawable.profile4, 0, R.drawable.profile5, R.drawable.profile6, R.drawable.profile7,}, 15 | {0, R.drawable.profile8, R.drawable.profile9, R.drawable.profile10, R.drawable.profile11, R.drawable.profile12}, 16 | {0, 0, 0, null, 0, 0, 0}, 17 | {0, 0, 0, 0, 0, 0}, 18 | {0, R.drawable.profile13, R.drawable.profile14, R.drawable.profile15, 0}, 19 | {null, 0, 0, null} 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/java/net/omplanet/hexagonalgrids/model/Grid.java: -------------------------------------------------------------------------------- 1 | package net.omplanet.hexagonalgrids.model; 2 | 3 | import android.graphics.Point; 4 | 5 | /** 6 | * * * * * 7 | * * * * * 8 | * * * * * 9 | * * * * * 10 | * * * * * 11 | * A grid of hex nodes with axial coordinates. 12 | */ 13 | public class Grid { 14 | public enum Shape { 15 | RECTANGLE, 16 | HEXAGON_POINTY_TOP 17 | } 18 | 19 | public final int radius; //The radius of the grid - the count of rings around the central node 20 | public final int scale; //The radius of the single node in grid 21 | public final Shape shape; //The shape of the grid 22 | 23 | //Derived node properties 24 | public final int width; //The width of the single hexagon node 25 | public final int height; //The height of the single hexagon node 26 | public final int centerOffsetX; //Relative center coordinate within one node 27 | public final int centerOffsetY; //Relative center coordinate within one node 28 | 29 | public Cube[] nodes; 30 | 31 | /** 32 | * Construing a Grid with a set of cubes, scale, and shape 33 | * @param radius The count of rings around the central node 34 | * @param scale The radius of the hexagon in pixels 35 | * @param shape The shape of the hexagon 36 | */ 37 | public Grid(int radius, int scale, Shape shape) { 38 | this.radius = radius; 39 | this.scale = scale; 40 | this.shape = shape; 41 | 42 | //Init derived node properties 43 | width = (int) (Math.sqrt(3) * scale); 44 | height = 2 * scale; 45 | centerOffsetX = width/2; 46 | centerOffsetY = height/2; 47 | 48 | //Init nodes 49 | switch (shape) { 50 | case HEXAGON_POINTY_TOP: 51 | generateHexagonalShape(radius); 52 | break; 53 | case RECTANGLE: 54 | generateRectangleShape(radius); 55 | break; 56 | } 57 | } 58 | 59 | public Point hexToPixel(Hex hex) { 60 | int x = 0; 61 | int y = 0; 62 | 63 | switch (shape) { 64 | case HEXAGON_POINTY_TOP: 65 | x = (int) (width * (hex.getQ() + 0.5 * hex.getR())); 66 | y = (int) (scale * 1.5 * hex.getR()); 67 | break; 68 | case RECTANGLE: 69 | //oddR alignment 70 | x = (int) (width * hex.getQ() + 0.5 * width * (hex.getR()%2)); 71 | y = (int) (scale * 1.5 * hex.getR()); 72 | break; 73 | } 74 | 75 | return new Point(x, y); 76 | } 77 | 78 | public Hex pixelToHex(float x, float y) { 79 | float q = (float) (Math.sqrt(3)/3 * x - 1/3 * y) / scale; 80 | float r = (2/3 * y) / scale; 81 | 82 | return new Hex(q, r); 83 | 84 | //TODO RECTANGLE 85 | } 86 | 87 | private void generateHexagonalShape(int radius) throws ArrayIndexOutOfBoundsException { 88 | nodes = new Cube[getNumberOfNodesInGrid(radius, shape)]; 89 | int i = 0; 90 | 91 | for (int x = -radius; x <= radius; x++) { 92 | for (int y = -radius; y <= radius; y++) { 93 | int z = -x-y; 94 | if (Math.abs(x) <= radius && Math.abs(y) <= radius && Math.abs(z) <= radius) { 95 | nodes[i++] = new Cube(x, y, z); 96 | } 97 | } 98 | } 99 | } 100 | 101 | private void generateRectangleShape(int radius) { 102 | int minQ=0; 103 | int maxQ=radius*2; 104 | int minR=0; 105 | int maxR=radius*2; 106 | 107 | nodes = new Cube[getNumberOfNodesInGrid(radius, shape)]; 108 | int i = 0; 109 | 110 | for (int q = minQ; q <= maxQ; q++) { 111 | for (int r = -minR; r <= maxR; r++) { 112 | nodes[i++] = new Hex(q,r).oddRHexToCube(); //conversion to cube is different for oddR coordinates 113 | } 114 | } 115 | } 116 | 117 | /** 118 | * @return Number of hexagons inside of a hex or oddR rectangle shaped grid with the given radius 119 | */ 120 | public static int getNumberOfNodesInGrid(int radius, Shape shape) { 121 | switch (shape) { 122 | case HEXAGON_POINTY_TOP: 123 | return (int) (3 * Math.pow(radius+1, 2) - 3 * (radius +1) + 1); 124 | case RECTANGLE: 125 | return (radius * 2 + 1) * (radius * 2 + 1); 126 | }; 127 | 128 | return 0; 129 | } 130 | 131 | public static int getGridWidth(int radius, int scale, Shape shape) { 132 | switch (shape) { 133 | case HEXAGON_POINTY_TOP: 134 | return (int) ((2*radius + 1) * Math.sqrt(3) * scale); 135 | case RECTANGLE: 136 | return 0; //TODO 137 | }; 138 | 139 | return 0; 140 | } 141 | 142 | public static int getGridHeight(int radius, int scale, Shape shape) { 143 | switch (shape) { 144 | case HEXAGON_POINTY_TOP: 145 | return (int) (scale * ((2*radius + 1) * 1.5 + 0.5)); 146 | case RECTANGLE: 147 | return 0; //TODO 148 | }; 149 | 150 | return 0; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/java/net/omplanet/hexagonalgrids/model/Hex.java: -------------------------------------------------------------------------------- 1 | package net.omplanet.hexagonalgrids.model; 2 | 3 | /** 4 | * Non-cube hex coordinates (q, r) 5 | */ 6 | public class Hex { 7 | private int q; //column 8 | private int r; //row 9 | 10 | public Hex (int q, int r) { 11 | this.q = q; 12 | this.r = r; 13 | } 14 | 15 | public Hex (float q, float r) { 16 | float x = q; 17 | float y = -q-r; 18 | float z = r; 19 | 20 | int rx = Math.round(x); 21 | int ry = Math.round(y); 22 | int rz = Math.round(z); 23 | 24 | float x_diff = Math.abs(rx - x); 25 | float y_diff = Math.abs(ry - y); 26 | float z_diff = Math.abs(rz - z); 27 | 28 | if (x_diff > y_diff && x_diff > z_diff) 29 | rx = -ry-rz; 30 | else if (y_diff > z_diff) 31 | ry = -rx-rz; 32 | 33 | this.q = rx; 34 | this.r = ry; 35 | } 36 | 37 | public Cube toCube() { 38 | return new Cube(q, -q-r, r); 39 | } 40 | 41 | public Cube oddRHexToCube() { 42 | int x = q - (r - (r&1)) / 2; 43 | int z = r; 44 | int y = -x-z; 45 | 46 | return new Cube(x, -x-z, z); 47 | } 48 | 49 | public String toString() { 50 | return q + ":" + r; 51 | } 52 | 53 | public int getQ() { 54 | return q; 55 | } 56 | 57 | public void setQ(int q) { 58 | this.q = q; 59 | } 60 | 61 | public int getR() { 62 | return r; 63 | } 64 | 65 | public void setR(int r) { 66 | this.r = r; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/java/net/omplanet/hexagonalgrids/model/StorageMap.java: -------------------------------------------------------------------------------- 1 | package net.omplanet.hexagonalgrids.model; 2 | 3 | import android.util.Log; 4 | 5 | import net.omplanet.hexagonalgrids.R; 6 | 7 | /** 8 | * Storage for Hex nodes with column:q and row:r. 9 | * Sliding the rows to the left, and using variable sized rows to save space. 10 | * The access formula is array[r][q + r/2] if the grid is arranged in rectangular shape. 11 | * The access formula is array[r + radius][q + radius + min(0, r)] if arranged in hexagonal shape. 12 | */ 13 | public class StorageMap { 14 | private static final String TAG = StorageMap.class.getName(); 15 | 16 | private int mRadius; 17 | private Grid.Shape mShape; 18 | private Object[][] mSquareMap; 19 | 20 | /** 21 | * Build a square grid that can cover the range of axial grid coordinates 22 | * @param radius The count of rings around the central node 23 | */ 24 | public StorageMap(int radius, Grid.Shape shape, Object[][] squareMap) { 25 | mRadius = radius; 26 | mShape = shape; 27 | mSquareMap = squareMap; 28 | } 29 | 30 | //Slide the rows to the left, and use variable sized rows. 31 | public Object getObjectByCoordinate(int q, int r) { 32 | try { 33 | switch (mShape) { 34 | case HEXAGON_POINTY_TOP: 35 | return mSquareMap[r + mRadius][q + mRadius + Math.min(0, r)]; 36 | case RECTANGLE: 37 | return mSquareMap[r][q]; 38 | } 39 | } catch (Exception e) { 40 | Log.d(TAG, "IndexOutOfBound, the array element is not found for " + q + ":" + r); 41 | } 42 | 43 | return null; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/java/net/omplanet/hexagonalgrids/ui/CircleImageView.java: -------------------------------------------------------------------------------- 1 | package net.omplanet.hexagonalgrids.ui; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapShader; 7 | import android.graphics.Canvas; 8 | import android.graphics.Color; 9 | import android.graphics.ColorFilter; 10 | import android.graphics.Matrix; 11 | import android.graphics.Paint; 12 | import android.graphics.RectF; 13 | import android.graphics.Shader; 14 | import android.graphics.drawable.BitmapDrawable; 15 | import android.graphics.drawable.ColorDrawable; 16 | import android.graphics.drawable.Drawable; 17 | import android.net.Uri; 18 | import android.util.AttributeSet; 19 | import android.widget.ImageView; 20 | 21 | import net.omplanet.hexagonalgrids.R; 22 | import net.omplanet.hexagonalgrids.model.Hex; 23 | 24 | public class CircleImageView extends ImageView { 25 | 26 | private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; 27 | 28 | private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; 29 | private static final int COLORDRAWABLE_DIMENSION = 2; 30 | 31 | private static final int DEFAULT_BORDER_WIDTH = 3; 32 | private static final int SELECTED_BORDER_WIDTH = 7; 33 | private static final int DEFAULT_BORDER_COLOR = Color.TRANSPARENT; 34 | private static final int SELECTED_BORDER_COLOR = Color.TRANSPARENT; 35 | 36 | private final RectF mDrawableRect = new RectF(); 37 | private final RectF mBorderRect = new RectF(); 38 | 39 | private final Matrix mShaderMatrix = new Matrix(); 40 | private final Paint mBitmapPaint = new Paint(); 41 | private final Paint mBorderPaint = new Paint(); 42 | 43 | private int mBorderColor = DEFAULT_BORDER_COLOR; 44 | private int mBorderWidth = DEFAULT_BORDER_WIDTH; 45 | 46 | private Bitmap mBitmap; 47 | private BitmapShader mBitmapShader; 48 | private int mBitmapWidth; 49 | private int mBitmapHeight; 50 | 51 | private float mDrawableRadius; 52 | private float mBorderRadius; 53 | 54 | private ColorFilter mColorFilter; 55 | 56 | private boolean mReady; 57 | private boolean mSetupPending; 58 | 59 | private Hex mHex; //Hold the node coordinates on the grid 60 | 61 | public CircleImageView(Context context) { 62 | super(context); 63 | 64 | init(); 65 | } 66 | 67 | public CircleImageView(Context context, AttributeSet attrs) { 68 | this(context, attrs, 0); 69 | } 70 | 71 | public CircleImageView(Context context, AttributeSet attrs, int defStyle) { 72 | super(context, attrs, defStyle); 73 | 74 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); 75 | 76 | mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH); 77 | mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR); 78 | 79 | a.recycle(); 80 | 81 | init(); 82 | } 83 | 84 | private void init() { 85 | super.setScaleType(SCALE_TYPE); 86 | mReady = true; 87 | 88 | if (mSetupPending) { 89 | setup(); 90 | mSetupPending = false; 91 | } 92 | } 93 | 94 | @Override 95 | public ScaleType getScaleType() { 96 | return SCALE_TYPE; 97 | } 98 | 99 | @Override 100 | public void setScaleType(ScaleType scaleType) { 101 | if (scaleType != SCALE_TYPE) { 102 | throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType)); 103 | } 104 | } 105 | 106 | @Override 107 | public void setAdjustViewBounds(boolean adjustViewBounds) { 108 | if (adjustViewBounds) { 109 | throw new IllegalArgumentException("adjustViewBounds not supported."); 110 | } 111 | } 112 | 113 | @Override 114 | protected void onDraw(Canvas canvas) { 115 | if (getDrawable() == null) { 116 | return; 117 | } 118 | 119 | canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint); 120 | if (mBorderWidth != 0) { 121 | canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint); 122 | } 123 | } 124 | 125 | @Override 126 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 127 | super.onSizeChanged(w, h, oldw, oldh); 128 | setup(); 129 | } 130 | 131 | public Hex getHex() { 132 | return mHex; 133 | } 134 | 135 | public void setHex(Hex hex) { 136 | mHex = hex; 137 | } 138 | 139 | public int getBorderColor() { 140 | return mBorderColor; 141 | } 142 | 143 | public void setBorderColor(int borderColor) { 144 | if (borderColor == mBorderColor) { 145 | return; 146 | } 147 | 148 | mBorderColor = borderColor; 149 | mBorderPaint.setColor(mBorderColor); 150 | invalidate(); 151 | } 152 | 153 | public void setSelected(boolean selected) { 154 | //super.setSelected(selected); 155 | 156 | if(selected) { 157 | mBorderColor = SELECTED_BORDER_COLOR; 158 | setBorderWidth(SELECTED_BORDER_WIDTH); 159 | } else { 160 | mBorderColor = DEFAULT_BORDER_COLOR; 161 | setBorderWidth(DEFAULT_BORDER_WIDTH); 162 | } 163 | } 164 | 165 | public int getBorderWidth() { 166 | return mBorderWidth; 167 | } 168 | 169 | public void setBorderWidth(int borderWidth) { 170 | if (borderWidth == mBorderWidth) { 171 | return; 172 | } 173 | 174 | mBorderWidth = borderWidth; 175 | setup(); 176 | } 177 | 178 | @Override 179 | public void setImageBitmap(Bitmap bm) { 180 | super.setImageBitmap(bm); 181 | mBitmap = bm; 182 | setup(); 183 | } 184 | 185 | @Override 186 | public void setImageDrawable(Drawable drawable) { 187 | super.setImageDrawable(drawable); 188 | mBitmap = getBitmapFromDrawable(drawable); 189 | setup(); 190 | } 191 | 192 | @Override 193 | public void setImageResource(int resId) { 194 | super.setImageResource(resId); 195 | mBitmap = getBitmapFromDrawable(getDrawable()); 196 | setup(); 197 | } 198 | 199 | @Override 200 | public void setImageURI(Uri uri) { 201 | super.setImageURI(uri); 202 | mBitmap = getBitmapFromDrawable(getDrawable()); 203 | setup(); 204 | } 205 | 206 | @Override 207 | public void setColorFilter(ColorFilter cf) { 208 | if (cf == mColorFilter) { 209 | return; 210 | } 211 | 212 | mColorFilter = cf; 213 | mBitmapPaint.setColorFilter(mColorFilter); 214 | invalidate(); 215 | } 216 | 217 | private Bitmap getBitmapFromDrawable(Drawable drawable) { 218 | if (drawable == null) { 219 | return null; 220 | } 221 | 222 | if (drawable instanceof BitmapDrawable) { 223 | return ((BitmapDrawable) drawable).getBitmap(); 224 | } 225 | 226 | try { 227 | Bitmap bitmap; 228 | 229 | if (drawable instanceof ColorDrawable) { 230 | bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); 231 | } else { 232 | bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); 233 | } 234 | 235 | Canvas canvas = new Canvas(bitmap); 236 | drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 237 | drawable.draw(canvas); 238 | return bitmap; 239 | } catch (OutOfMemoryError e) { 240 | return null; 241 | } 242 | } 243 | 244 | private void setup() { 245 | if (!mReady) { 246 | mSetupPending = true; 247 | return; 248 | } 249 | 250 | if (mBitmap == null) { 251 | return; 252 | } 253 | 254 | mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); 255 | 256 | mBitmapPaint.setAntiAlias(true); 257 | mBitmapPaint.setShader(mBitmapShader); 258 | 259 | mBorderPaint.setStyle(Paint.Style.STROKE); 260 | mBorderPaint.setAntiAlias(true); 261 | mBorderPaint.setColor(mBorderColor); 262 | mBorderPaint.setStrokeWidth(mBorderWidth); 263 | 264 | mBitmapHeight = mBitmap.getHeight(); 265 | mBitmapWidth = mBitmap.getWidth(); 266 | 267 | mBorderRect.set(0, 0, getWidth(), getHeight()); 268 | mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2); 269 | 270 | mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth); 271 | mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2); 272 | 273 | updateShaderMatrix(); 274 | invalidate(); 275 | } 276 | 277 | private void updateShaderMatrix() { 278 | float scale; 279 | float dx = 0; 280 | float dy = 0; 281 | 282 | mShaderMatrix.set(null); 283 | 284 | if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { 285 | scale = mDrawableRect.height() / (float) mBitmapHeight; 286 | dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; 287 | } else { 288 | scale = mDrawableRect.width() / (float) mBitmapWidth; 289 | dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; 290 | } 291 | 292 | mShaderMatrix.setScale(scale, scale); 293 | mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth, (int) (dy + 0.5f) + mBorderWidth); 294 | 295 | mBitmapShader.setLocalMatrix(mShaderMatrix); 296 | } 297 | 298 | } -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/java/net/omplanet/hexagonalgrids/ui/MainActivity.java: -------------------------------------------------------------------------------- 1 | package net.omplanet.hexagonalgrids.ui; 2 | 3 | import android.content.Intent; 4 | import android.graphics.Point; 5 | import android.os.Bundle; 6 | import android.support.v7.app.ActionBarActivity; 7 | import android.view.Display; 8 | import android.view.Menu; 9 | import android.view.MenuItem; 10 | import android.view.MotionEvent; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.RelativeLayout; 14 | import android.widget.Toast; 15 | 16 | import net.omplanet.hexagonalgrids.R; 17 | import net.omplanet.hexagonalgrids.model.Cube; 18 | import net.omplanet.hexagonalgrids.model.Grid; 19 | import net.omplanet.hexagonalgrids.model.Hex; 20 | import net.omplanet.hexagonalgrids.model.DemoObjects; 21 | import net.omplanet.hexagonalgrids.model.StorageMap; 22 | 23 | public class MainActivity extends ActionBarActivity { 24 | 25 | private RelativeLayout mRelativeLayout; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_main); 31 | 32 | mRelativeLayout = (RelativeLayout) findViewById(R.id.gridLayout); 33 | 34 | Grid.Shape shape = Grid.Shape.HEXAGON_POINTY_TOP; 35 | int radius = 3; 36 | 37 | Bundle extras = getIntent().getExtras(); 38 | if (extras != null) { 39 | radius = extras.getInt("GRID_RADIUS", 3); 40 | shape = Grid.Shape.valueOf(extras.getString("GRID_SHAPE")); 41 | if (shape == null) { 42 | radius = 3; 43 | shape = Grid.Shape.HEXAGON_POINTY_TOP; 44 | } 45 | } 46 | 47 | initGridView(radius, shape); 48 | } 49 | 50 | private void initGridView(int radius, Grid.Shape shape) { 51 | int scale = setGridDimensions(radius, shape); 52 | 53 | //Init node elements 54 | Grid grid = setGridNodes(radius, scale, shape); 55 | 56 | //Init zoom buttons 57 | setGridButtons(grid); 58 | } 59 | 60 | private int setGridDimensions(int radius, Grid.Shape shape) { 61 | // Gets the layout params that will allow to resize the layout 62 | ViewGroup.LayoutParams params = mRelativeLayout.getLayoutParams(); 63 | 64 | //Get display metrics 65 | Display display = getWindowManager().getDefaultDisplay(); 66 | Point size = new Point(); 67 | display.getSize(size); 68 | int displayWidth = size.x; 69 | int displayHeight = size.y; 70 | 71 | //If in landscape mode, keep the width small as in portrait mode 72 | if(displayWidth > displayHeight) displayWidth = displayHeight; 73 | 74 | int horizontalPadding = (int) getResources().getDimension(R.dimen.activity_horizontal_margin); 75 | //int horizontalPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, horizontalPaddingInDp, getResources().getDisplayMetrics()); 76 | displayWidth -= 2 * horizontalPadding; 77 | 78 | // Calculate the scale: the radius of single node. 79 | int scale = (int) (displayWidth / ((2*radius + 1) * (Math.sqrt(3)))); 80 | 81 | // Changes the height and width of the grid to the specified *pixels* 82 | params.width = Grid.getGridWidth(radius, scale, shape); 83 | params.height = Grid.getGridHeight(radius, scale, shape); 84 | 85 | return scale; 86 | } 87 | 88 | private void setGridButtons(final Grid grid) { 89 | int scale = Grid.getGridWidth(grid.radius, grid.scale, grid.shape) / 16; 90 | 91 | View zoomOutButton = findViewById(R.id.zoomOutButton); 92 | ViewGroup.LayoutParams params = zoomOutButton.getLayoutParams(); 93 | params.width = scale; 94 | params.height = scale; 95 | 96 | View zoomInButton = findViewById(R.id.zoomInButton); 97 | params = zoomInButton.getLayoutParams(); 98 | params.width = scale; 99 | params.height = scale; 100 | 101 | zoomOutButton.setOnClickListener(new View.OnClickListener() { 102 | @Override 103 | public void onClick(View v) { 104 | int newRadius = grid.radius+1; 105 | if(newRadius > 12) return; 106 | 107 | //Restart the activity with the new parameters 108 | Intent intent = new Intent(MainActivity.this, MainActivity.class); 109 | intent.putExtra("GRID_RADIUS", newRadius); 110 | intent.putExtra("GRID_SHAPE", grid.shape.name()); 111 | startActivity(intent); 112 | finish(); 113 | 114 | //Remove all the elements from the view except the side buttons 115 | // final ViewGroup viewGroup = (ViewGroup) findViewById(R.id.container_layout); 116 | // viewGroup.removeAllViews(); 117 | // mRelativeLayout = (RelativeLayout) View.inflate(MainActivity.this, R.layout.hex_grid_layout, null); 118 | // viewGroup.addView(mRelativeLayout); 119 | // viewGroup.invalidate(); 120 | } 121 | }); 122 | 123 | zoomInButton.setOnClickListener(new View.OnClickListener() { 124 | @Override 125 | public void onClick(View v) { 126 | int newRadius = grid.radius-1; 127 | if(newRadius < 0) return; 128 | 129 | //Restart the activity with the new parameters 130 | Intent intent = new Intent(MainActivity.this, MainActivity.class); 131 | intent.putExtra("GRID_RADIUS", newRadius); 132 | intent.putExtra("GRID_SHAPE", grid.shape.name()); 133 | startActivity(intent); 134 | finish(); 135 | 136 | //Remove all the elements from the view except the side buttons 137 | // mRelativeLayout.removeAllViews(); 138 | // initGridView(newRadius, grid.shape); 139 | // mRelativeLayout.invalidate(); 140 | } 141 | }); 142 | } 143 | 144 | private Grid setGridNodes(int radius, int scale, Grid.Shape shape) { 145 | try { 146 | StorageMap storageMap = new StorageMap(radius, shape, DemoObjects.squareMap); 147 | final Grid grid = new Grid(radius, scale, shape); 148 | 149 | //Gird node listener restricted to the node's circular area. 150 | View.OnTouchListener gridNodeTouchListener = new View.OnTouchListener() { 151 | 152 | @Override 153 | public boolean onTouch(final View v, MotionEvent event) { 154 | switch (event.getAction()) { 155 | case MotionEvent.ACTION_DOWN: 156 | float xPoint = event.getX(); 157 | float yPoint = event.getY(); 158 | //Hex hex = grid.pixelToHex(event.getX(), event.getY()); //This can work on the RelativeLayout grid area 159 | boolean isPointOutOfCircle = (grid.centerOffsetX -xPoint)*(grid.centerOffsetX -xPoint) + (grid.centerOffsetY -yPoint)*(grid.centerOffsetY -yPoint) > grid.width * grid.width / 4; 160 | 161 | if (isPointOutOfCircle) return false; 162 | else v.setSelected(true); 163 | break; 164 | case MotionEvent.ACTION_OUTSIDE: 165 | break; 166 | case MotionEvent.ACTION_CANCEL: 167 | break; 168 | case MotionEvent.ACTION_MOVE: 169 | break; 170 | case MotionEvent.ACTION_SCROLL: 171 | break; 172 | case MotionEvent.ACTION_UP: 173 | v.setSelected(false); 174 | CircleImageView view = (CircleImageView) v; 175 | OnGridHexClick(view.getHex()); 176 | break; 177 | } 178 | return true; 179 | } 180 | }; 181 | 182 | for(Cube cube : grid.nodes) { 183 | Hex hex = null; 184 | switch (shape) { 185 | case HEXAGON_POINTY_TOP: 186 | hex = cube.toHex(); 187 | break; 188 | case RECTANGLE: 189 | hex = cube.cubeToOddRHex(); 190 | break; 191 | } 192 | 193 | CircleImageView view = new CircleImageView(this); 194 | Integer pic = (Integer) storageMap.getObjectByCoordinate(hex.getQ(), hex.getR()); 195 | if(pic == null) { 196 | view.setHex(hex); 197 | view.setOnTouchListener(gridNodeTouchListener); 198 | // view.setBackgroundResource(R.drawable.ring); 199 | view.setBackgroundResource(R.drawable.empty_image); 200 | } else { 201 | view = new CircleImageView(this); 202 | //view.setBackgroundResource(R.drawable.hexagon); 203 | view.setOnTouchListener(gridNodeTouchListener); 204 | view.setHex(hex); 205 | if(pic != 0) { 206 | view.setImageResource(pic); 207 | } else { 208 | view.setImageResource(R.drawable.no_profile_image); 209 | } 210 | } 211 | addViewToLayout(view, hex, grid); 212 | } 213 | 214 | return grid; 215 | } catch (Exception e) { 216 | Toast.makeText(MainActivity.this, "Sorry, there was a problem initializing the application.", Toast.LENGTH_LONG).show(); 217 | e.printStackTrace(); 218 | } 219 | 220 | return null; 221 | } 222 | 223 | private void addViewToLayout(View view, Hex hex, Grid grid) { 224 | //Add to view 225 | RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(grid.width, grid.height); 226 | params.addRule(RelativeLayout.RIGHT_OF, R.id.centerLayout); 227 | params.addRule(RelativeLayout.BELOW, R.id.centerLayout); 228 | mRelativeLayout.addView(view, params); 229 | 230 | //Set coordinates 231 | Point p = grid.hexToPixel(hex); 232 | switch (grid.shape) { 233 | case HEXAGON_POINTY_TOP: 234 | params.leftMargin = -grid.centerOffsetX + p.x; 235 | params.topMargin = -grid.centerOffsetY + p.y; 236 | break; 237 | case RECTANGLE: 238 | params.leftMargin = -grid.width * grid.radius -grid.centerOffsetX + p.x; 239 | params.topMargin = (int) (-1.5 * grid.scale * grid.radius -grid.centerOffsetY + p.y); 240 | break; 241 | } 242 | } 243 | 244 | private void OnGridHexClick(Hex hex) { 245 | Toast.makeText(MainActivity.this, "OnGridHexClick: " + hex, Toast.LENGTH_SHORT).show(); 246 | } 247 | 248 | @Override 249 | public boolean onCreateOptionsMenu(Menu menu) { 250 | // Inflate the menu; this adds items to the action bar if it is present. 251 | getMenuInflater().inflate(R.menu.menu_main, menu); 252 | return true; 253 | } 254 | 255 | @Override 256 | public boolean onOptionsItemSelected(MenuItem item) { 257 | // Handle action bar item clicks here. The action bar will 258 | // automatically handle clicks on the Home/Up button, so long 259 | // as you specify a parent activity in AndroidManifest.xml. 260 | int id = item.getItemId(); 261 | 262 | //noinspection SimplifiableIfStatement 263 | if (id == R.id.action_settings) { 264 | return true; 265 | } 266 | 267 | return super.onOptionsItemSelected(item); 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/empty_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/empty_image.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/no_profile_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/no_profile_image.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile1.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile10.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile11.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile12.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile13.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile14.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile15.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile2.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile3.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile4.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile5.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile6.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile7.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile8.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/profile9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/profile9.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/ring.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/zoom_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/zoom_in.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/drawable/zoom_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/drawable/zoom_out.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/layout/hex_grid_layout.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 21 | 22 | 28 | 29 | 37 | 38 | 46 | 47 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Hexagonal Grids 3 | 4 | Settings 5 | 6 | -------------------------------------------------------------------------------- /HexagonalGrids/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /HexagonalGrids/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.0.1' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /HexagonalGrids/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /HexagonalGrids/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/HexagonalGrids/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /HexagonalGrids/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 10 15:27:10 PDT 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip 7 | -------------------------------------------------------------------------------- /HexagonalGrids/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /HexagonalGrids/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /HexagonalGrids/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # android-hexagonal-grids 2 | Android app implementing [Hexagonal Grids][1] model with the [CircleImageView][2] nodes. 3 | 4 | [1]: http://www.redblobgames.com/grids/hexagons/ 5 | [2]: https://github.com/hdodenhof/CircleImageView 6 | -------------------------------------------------------------------------------- /Screenshots/Screenshot_2015-03-02-19-11-43.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/Screenshots/Screenshot_2015-03-02-19-11-43.png -------------------------------------------------------------------------------- /Screenshots/Screenshot_2015-03-02-19-11-49.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/Screenshots/Screenshot_2015-03-02-19-11-49.png -------------------------------------------------------------------------------- /Screenshots/Screenshot_2015-03-02-19-11-53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/Screenshots/Screenshot_2015-03-02-19-11-53.png -------------------------------------------------------------------------------- /Screenshots/Screenshot_2015-03-02-19-11-56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/Screenshots/Screenshot_2015-03-02-19-11-56.png -------------------------------------------------------------------------------- /Screenshots/Screenshot_2015-03-02-19-12-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/Screenshots/Screenshot_2015-03-02-19-12-09.png -------------------------------------------------------------------------------- /Screenshots/Screenshot_2015-03-02-19-13-57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/Screenshots/Screenshot_2015-03-02-19-13-57.png -------------------------------------------------------------------------------- /Screenshots/Screenshot_2015-03-02-19-14-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/Screenshots/Screenshot_2015-03-02-19-14-02.png -------------------------------------------------------------------------------- /Screenshots/Screenshot_2015-03-02-19-14-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/Screenshots/Screenshot_2015-03-02-19-14-11.png -------------------------------------------------------------------------------- /Screenshots/Screenshot_2015-03-02-19-14-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omplanet/android-hexagonal-grids/29e011e966ed38d4dcd504d6d20b86fddcb9e30f/Screenshots/Screenshot_2015-03-02-19-14-22.png --------------------------------------------------------------------------------