I new to Unity. I'm trying to re-write game from the site in Unity http://www.boxcar2d.com/index.html
So I found that I should work with Sprites. Now I am trying to dynamically generate an arbitrarily shaped "car". I need it to collide and interact with physics and gravity.
I tried to use Mesh but it seems like there is no way to turn Mesh into a Sprite and work with it like with physical object.
What kind of structures or approach should I use for creating those "cars" dynamically?
Here is my code so far if that somehow will be useful.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GenerateCar : MonoBehaviour {
public Material mat;
// Use this for initialization
void Start()
{
Mesh mesh = new Mesh();
Vector3[] vertices = new Vector3[6];
vertices[0] = new Vector3(0, 0);
vertices[1] = new Vector3(4, 1);
vertices[2] = new Vector3(3, -1);
vertices[3] = new Vector3(-1, -3);
vertices[4] = new Vector3(3, -6);
vertices[5] = new Vector3(0, 1);
//vertices[6] = new Vector3(width, height);
//vertices[7] = new Vector3(width, -height);
mesh.vertices = vertices;
mesh.triangles = new int[] { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 1};
GetComponent<MeshRenderer>().material = mat;
GetComponent<MeshFilter>().mesh = mesh;
}
}
If you need to make arbitrary shapes that can't be made with just horizontally and vertically stretching sprites you make ahead of time, then sprites aren't suitable. A Mesh would be more practical.
If you can describe the shape you want to make as a polygon with a known ordered list of points, you can use the community Triangulator class to create a Mesh. There are other methods, but this is a community standby.
Whatever you use to make the Mesh, you will need to make sure there is also a PolygonCollider2D on the same object as the Mesh. You can use SetPath to create its outline using the same points as you fed into Triangulator. You will also need a Rigidbody2D to handle physics and collision for the body of the car. I've never worked with wheels but WheelJoint2D might be what you can use for the wheels.
Triangulator Usage Example
using UnityEngine;
public class PolygonTester : MonoBehaviour {
void Start () {
// Create Vector2 vertices
Vector2[] vertices2D = new Vector2[] {
new Vector2(0,0),
new Vector2(0,50),
new Vector2(50,50),
new Vector2(50,100),
new Vector2(0,100),
new Vector2(0,150),
new Vector2(150,150),
new Vector2(150,100),
new Vector2(100,100),
new Vector2(100,50),
new Vector2(150,50),
new Vector2(150,0),
};
// Use the triangulator to get indices for creating triangles
Triangulator tr = new Triangulator(vertices2D);
int[] indices = tr.Triangulate();
// Create the Vector3 vertices
Vector3[] vertices = new Vector3[vertices2D.Length];
for (int i=0; i<vertices.Length; i++) {
vertices[i] = new Vector3(vertices2D[i].x, vertices2D[i].y, 0);
}
// Create the mesh
Mesh msh = new Mesh();
msh.vertices = vertices;
msh.triangles = indices;
msh.RecalculateNormals();
msh.RecalculateBounds();
// Set up game object with mesh;
gameObject.AddComponent(typeof(MeshRenderer));
MeshFilter filter = gameObject.AddComponent(typeof(MeshFilter)) as MeshFilter;
filter.mesh = msh;
}
}
Triangulator source
using UnityEngine;
using System.Collections.Generic;
public class Triangulator
{
private List<Vector2> m_points = new List<Vector2>();
public Triangulator (Vector2[] points) {
m_points = new List<Vector2>(points);
}
public int[] Triangulate() {
List<int> indices = new List<int>();
int n = m_points.Count;
if (n < 3)
return indices.ToArray();
int[] V = new int[n];
if (Area() > 0) {
for (int v = 0; v < n; v++)
V[v] = v;
}
else {
for (int v = 0; v < n; v++)
V[v] = (n - 1) - v;
}
int nv = n;
int count = 2 * nv;
for (int m = 0, v = nv - 1; nv > 2; ) {
if ((count--) <= 0)
return indices.ToArray();
int u = v;
if (nv <= u)
u = 0;
v = u + 1;
if (nv <= v)
v = 0;
int w = v + 1;
if (nv <= w)
w = 0;
if (Snip(u, v, w, nv, V)) {
int a, b, c, s, t;
a = V[u];
b = V[v];
c = V[w];
indices.Add(a);
indices.Add(b);
indices.Add(c);
m++;
for (s = v, t = v + 1; t < nv; s++, t++)
V[s] = V[t];
nv--;
count = 2 * nv;
}
}
indices.Reverse();
return indices.ToArray();
}
private float Area () {
int n = m_points.Count;
float A = 0.0f;
for (int p = n - 1, q = 0; q < n; p = q++) {
Vector2 pval = m_points[p];
Vector2 qval = m_points[q];
A += pval.x * qval.y - qval.x * pval.y;
}
return (A * 0.5f);
}
private bool Snip (int u, int v, int w, int n, int[] V) {
int p;
Vector2 A = m_points[V[u]];
Vector2 B = m_points[V[v]];
Vector2 C = m_points[V[w]];
if (Mathf.Epsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x))))
return false;
for (p = 0; p < n; p++) {
if ((p == u) || (p == v) || (p == w))
continue;
Vector2 P = m_points[V[p]];
if (InsideTriangle(A, B, C, P))
return false;
}
return true;
}
private bool InsideTriangle (Vector2 A, Vector2 B, Vector2 C, Vector2 P) {
float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
float cCROSSap, bCROSScp, aCROSSbp;
ax = C.x - B.x; ay = C.y - B.y;
bx = A.x - C.x; by = A.y - C.y;
cx = B.x - A.x; cy = B.y - A.y;
apx = P.x - A.x; apy = P.y - A.y;
bpx = P.x - B.x; bpy = P.y - B.y;
cpx = P.x - C.x; cpy = P.y - C.y;
aCROSSbp = ax * bpy - ay * bpx;
cCROSSap = cx * apy - cy * apx;
bCROSScp = bx * cpy - by * cpx;
return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
}
}
Related
Codes below:
using System;
using UnityEngine;
using UnityEngine.Serialization;
public class Chessboard : MonoBehaviour
{
[Header("Art")]
[SerializeField] private Material tileMaterial;
//Logic
private const int TILE_COUNT_X = 8;
private const int TILE_COUNT_Y = 8;
private GameObject[,] tiles;
private Camera currentCamera;
private Vector2Int currentHover = -Vector2Int.one;
private void Awake()
{
GenerateAllTiles(1, TILE_COUNT_X, TILE_COUNT_Y);
}
private void Update()
{
if (!currentCamera)
{
currentCamera = Camera.current;
return;
}
RaycastHit info;
Ray ray = currentCamera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out info, 100, LayerMask.GetMask("Tile")))
{
// get the indexes of Tile i've hit
Vector2Int hitPosition = LookupTileIndex(info.transform.gameObject);
//If we are hovering a tile after not hovering any
if (currentHover == -Vector2Int.one)
{
tiles[hitPosition.x, hitPosition.y].layer = LayerMask.NameToLayer("Hover");
currentHover = hitPosition;
}
//If we were already hovering a tile, change the previous one
else if (currentHover != hitPosition)
{
tiles[currentHover.x, currentHover.y].layer = LayerMask.NameToLayer("Tile");
currentHover = hitPosition;
tiles[hitPosition.x, hitPosition.y].layer = LayerMask.NameToLayer("Hover");
}
}
else
{
if (currentHover != -Vector2Int.one)
{
tiles[currentHover.x, currentHover.y].layer = LayerMask.NameToLayer("Tile");
currentHover = -Vector2Int.one;
}
}
}
//Generate the board (useful)
private void GenerateAllTiles(float tileSize, int tileCountX, int tileCountY)
{
tiles = new GameObject[tileCountX, tileCountY];
for (int x = 0; x < tileCountX; x++)
for (int y = 0; y < tileCountY; y++)
tiles[x, y] = generate1tile(tileSize, x, y);
}
private GameObject generate1tile(float tileSize, int x, int y)
{
GameObject tileObject = new GameObject(string.Format("Tile X:{0}, Y:{1}", x, y));
tileObject.transform.parent = transform;
Mesh mesh = new Mesh();
tileObject.AddComponent<MeshFilter>().mesh = mesh;
tileObject.AddComponent<MeshRenderer>().material = tileMaterial;
Vector3[] vertices = new Vector3[4];
vertices[0] = new Vector3(x * tileSize, 0, y * tileSize);
vertices[1] = new Vector3(x * tileSize, 0, (y + 1) * tileSize);
vertices[2] = new Vector3((x + 1) * tileSize, 0, y * tileSize);
vertices[3] = new Vector3((x + 1) * tileSize, 0, (y + 1) * tileSize);
int[] tris = new int[]{0, 2, 1, 1, 2, 3};
mesh.vertices = vertices;
mesh.triangles = tris;
mesh.RecalculateNormals();
tileObject.layer = LayerMask.NameToLayer("Tile");
tileObject.AddComponent<BoxCollider>();
return tileObject;
}
private Vector2Int LookupTileIndex(GameObject hitInfo)
{
for(int x = 0; x < TILE_COUNT_X; x++)
for(int y = 0; y < TILE_COUNT_Y; y++)
if(tiles[x, y] == hitInfo)
return new Vector2Int(x, y);
return new Vector2Int(-1, -1); //Invalid
}
}
Error Message:
A game object can only be in one layer. The layer needs to be in the range [0...31]
UnityEngine.StackTraceUtility:ExtractStackTrace ()
Chessboard:generate1tile (single,int,int) (at Assets/scripts/Chessboard.cs:93)
Chessboard:GenerateAllTiles (single,int,int) (at Assets/scripts/Chessboard.cs:68)
Chessboard:Awake () (at Assets/scripts/Chessboard.cs:20)
I just get into Unity, so I might be missed some parts of it.
I tired using AI to config my problem, but it doesn't work. I am expecting i put my mouse on a tile, the tile change its color.
Here is the link to the tutorial I watched: https://www.youtube.com/watch?v=FtGy7J8XD90&list=PLmcbjnHce7SeAUFouc3X9zqXxiPbCz8Zp&index=2&ab_channel=Epitome
I am doing image processing so that I am finding contours in the image. What I need is the centroid pixel number of the found contour in the image. To find the pixel number I am using the code given below.
After finding the pixel number I want to show it in the text boxes as x and y coordinates. But the code is not working.
Please help me. What is wrong?
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
CvInvoke.FindContours(cannyImage, contours, null, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
var cannyOut = cannyImage.ToImage<Bgr, byte>();
//CvInvoke.DrawContours(cannyOut, contours, 2, new MCvScalar(255, 0, 0),2);
VectorOfPoint approx = new VectorOfPoint();
Dictionary<int, double> shapes = new Dictionary<int, double>();
for (int i = 0; i < contours.Size; i++)
{
approx.Clear();
double perimeter = CvInvoke.ArcLength(contours[i], true);
CvInvoke.ApproxPolyDP(contours[i], approx, 0.04 * perimeter, true);
double area = CvInvoke.ContourArea(contours[i]);
if (approx.Size > 4)
{
shapes.Add(i, area);
}
}
if (shapes.Count > 0)
{
var sortedShapes = (from item in shapes
orderby item.Value ascending
select item).ToList();
for (int i = 0; i < sortedShapes.Count; i++)
{
CvInvoke.DrawContours(cannyOut, contours, sortedShapes[i].Key, new MCvScalar(255, 0, 0), 2);
var moments = CvInvoke.Moments(contours[sortedShapes[i].Key]);
int x = (int)(moments.M10 / moments.M00);
int y = (int)(moments.M01 / moments.M00);
CvInvoke.PutText(cannyOut, (i + 1).ToString(), new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyTriplex, 1.0,
new MCvScalar(255, 0, 0), 2);
//CvInvoke.PutText(cannyOut, sortedShapes[i].Value.ToString(), new Point(x, y - 30), Emgu.CV.CvEnum.FontFace.HersheyTriplex, 1.0,
// new MCvScalar(255, 0, 0), 2);
textBox1.Text = x.ToString();
textBox2.Text = y.ToString();
}
}
To find the centroid of a shape you need to split it into many triangles first.
Then for each triangle with vertices A, B, C you do the summation weighted by the area of the triangle just as so
static void Main(string[] args)
{
var shape = new List<Triangle>();
// fill shape with triangles
float area = 0f;
Vector2 centroid = Vector2.Zero;
foreach (var triangle in shape)
{
float trig_area = triangle.Area;
Vector2 trig_cen = triangle.Centroid;
area += trig_area;
centroid += trig_area * trig_cen;
}
centroid /= area;
}
For reference, a 2D triangle has the following properties
public readonly struct Triangle
{
public Triangle(Vector2 a, Vector2 b, Vector2 c) : this()
{
A = a;
B = b;
C = c;
}
public Vector2 A { get; }
public Vector2 B { get; }
public Vector2 C { get; }
public float Area { get => (Cross(A, B) + Cross(B, C) + Cross(C, A)) / 2; }
public Vector2 Centroid { get => (A + B + C) / 3; }
// helper function
static float Cross(Vector2 a, Vector2 b) => a.X * b.Y - a.Y * b.X;
}
I want to generate a cube and subdivide each face of the cube 4 times, in this way a cube of 6 faces will have 24 faces. I'm am trying doing this in Unity3d but its giving me Out of Memory Exception when I try executing it. I think it may be due to some bad efficient code, but I think I'm missing something because I'm trying to see if I can make it more efficient and I don't really see nothing very bad.
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class sphereMesh : MonoBehaviour
{
// Start is called before the first frame update
Mesh mesh;
List<Vector3> vertices = new List<Vector3>();
List<int> triangulos = new List<int>();
public int numeroSubdivisiones = 1;
static Vector3[] faceCubes = {
new Vector3(1, 1, 1), //0
new Vector3(-1, 1, 1), //1
new Vector3(-1, -1, 1), //2
new Vector3(1, -1, 1), //3
new Vector3(-1, 1, -1), //4
new Vector3(1, 1, -1), //5
new Vector3(1, -1, -1), //6
new Vector3(-1, -1, -1) //7
};
static int[][] facetriangulos = {
// Cara trasera
new int[]{0,1,2,3},
// Cara derecha
new int[]{5,0,3,6},
// Cara frontal
new int[]{4,5,6,7},
// Cara izquierda
new int[]{1,4,7,2},
// Cara arriba
new int[]{5,4,1,0},
// Cara abajo
new int[]{3,2,7,6},
};
void MakeFace(int dir)
{
vertices.AddRange(faceVertices(dir));
int vCount = vertices.Count;
triangulos.Add(vCount - 4);
triangulos.Add(vCount - 4 + 1);
triangulos.Add(vCount - 4 + 2);
triangulos.Add(vCount - 4);
triangulos.Add(vCount - 4 + 2);
triangulos.Add(vCount - 4 + 3);
}
void MakeCube()
{
vertices = new List<Vector3>();
triangulos = new List<int>();
for (int i = 0; i <6; i++)
{
MakeFace(i);
}
}
// Funcion que crea una cara de vertices
public static Vector3[] faceVertices(int dir)
{
Vector3[] fv = new Vector3[4];
for (int i = 0; i < fv.Length; i++)
{
// La direccion y la posicion del array
fv[i] = faceCubes[facetriangulos[dir][i]];
}
return fv;
}
// Modifica la lista de vertices y la actualiza
// De forma que un cuadrado da lugar a otros cuatro cuadrados
// T --> Top, D --> Down, L --> Left, R --> Right
// v --> Vertice
void subdividirCuadrado(Vector3 vTL, Vector3 vTR, Vector3 vDL, Vector3 vDR)
{
Vector3 vT = vT = Vector3.Lerp(vTR, vTL, 0.5f);
Vector3 vD = vD = Vector3.Lerp(vDR, vDL, 0.5f);
Vector3 vR = vR = Vector3.Lerp(vTR,vDR, 0.5f);
Vector3 vL = vL = Vector3.Lerp(vTL,vDL, 0.5f);
Vector3 vCenter = Vector3.Lerp(vR, vL, 0.5f);
int size = vertices.Count;
vertices.AddRange(new List<Vector3> {vT, vD, vL, vR, vTL, vTR, vDL, vDR, vCenter});
int tT = size + 0;
int tD = size + 1;
int tL = size + 2;
int tR = size + 3;
int tTL = size + 4;
int tTR = size + 5;
int tDL = size + 6;
int tDR = size + 7;
int tCenter = size + 8;
triangulos.AddRange(new List<int> {tL, tTL, tT});
triangulos.AddRange(new List<int> {tL, tT, tCenter});
triangulos.AddRange(new List<int> {tCenter, tT, tTR});
triangulos.AddRange(new List<int> {tCenter, tTR, tR});
triangulos.AddRange(new List<int> {tDL, tL, tCenter});
triangulos.AddRange(new List<int> {tDL, tCenter, tD});
triangulos.AddRange(new List<int> {tD, tCenter, tR});
triangulos.AddRange(new List<int> {tD, tR, tDR});
}
void subCubo()
{
for(int j = 0; j < numeroSubdivisiones; j++)
{
Debug.Log("AAAAA" + vertices.Count);
for (int i = 0; i < vertices.Count; i += 4)
{
subdividirCuadrado(vertices[i], vertices[i+1], vertices[i+2], vertices[i+3]);
/*
mesh.vertices[i][0] = mesh.vertices[i][0]/i;
mesh.vertices[i][1] = mesh.vertices[i][1]/i;
mesh.vertices[i][2] = mesh.vertices[i][2]/i;
mesh.vertices[i+1][0] = mesh.vertices[i+1][0]/i+1;
mesh.vertices[i+1][1] = mesh.vertices[i+1][1]/i+1;
mesh.vertices[i+1][2] = mesh.vertices[i+1][2]/i+1;
mesh.vertices[i+2][0] = mesh.vertices[i+2][0]/i+2;
mesh.vertices[i+2][1] = mesh.vertices[i+2][1]/i+2;
mesh.vertices[i+2][2] = mesh.vertices[i+2][2]/i+2;
mesh.vertices[i+3][0] = mesh.vertices[i+3][0]/i+3;
mesh.vertices[i+3][1] = mesh.vertices[i+3][1]/i+3;
mesh.vertices[i+3][2] = mesh.vertices[i+3][2]/i+3;
*/
}
}
}
void Awake()
{
mesh = GetComponent<MeshFilter>().mesh;
}
void Start()
{
MakeCube();
subCubo();
UpdateMesh();
}
// Update is called once per frame
void UpdateMesh()
{
mesh.Clear();
mesh.vertices = vertices.ToArray();
mesh.triangles = triangulos.ToArray();
mesh.RecalculateNormals();
}
}
I think this is infinity loop:
for (int i = 0; i < vertices.Count; i += 4)
{
subdividirCuadrado(vertices[i], vertices[i+1], vertices[i+2], vertices[i+3]);
You keep going through the loop until i is bigger than count of items in vertices.
During each iteration i is increased by 4, but there are 9 new items in vertices:
vertices.AddRange(new List<Vector3> {vT, vD, vL, vR, vTL, vTR, vDL, vDR, vCenter});
Therefore i is never bigger than vertices.count and thus the loop is infinite.
vertices.AddRange(new List { vT, vD, vL, vR, vTL, vTR, vDL, vDR, vCenter });
This line inside subdividirCuadrado()
You add 9 NEW vertices to the vertices list but its inside
for (int i = 0; i < vertices.Count; i += 4).
Result is the count keep going up and up and up. To infinity :)
Here is my code :
BetBoard_Test.cs
//Scoreboard
[SerializeField] protected GameObject prefab_big_road = null;
[SerializeField] Transform pos_big_road = null;
string jsonString = "[1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1]"; //sample data
private void Start()
{
ExampleClass dataParser = new ExampleClass();
dataParser.dataToParse = jsonString;
//Convert to Json
string exampleClassToJson = JsonUtility.ToJson(dataParser);
Debug.Log(exampleClassToJson);
ExampleClass obj = JsonUtility.FromJson<ExampleClass>(exampleClassToJson);
//Loop over it
for (int i = 1; i < obj.dataToParse.Length - 1; i += 3)
{
char indivisualChar = obj.dataToParse[i];
Debug.Log(indivisualChar);
}
WinLog();
}
IEnumerator WinLog_big_road()
{
DeleteChildrens(pos_big_road);
yield return new WaitForEndOfFrame();
int[] array_big_road = tzPlayInfo.Instance._BIG_ROAD_;
for (int i = 0; i < rh.Const._HISTORY_COUNT_ * rh.Const._HISTORY_HEIGHT_; i++)
{
if (array_big_road[i] == 0) continue;
int x = i % rh.Const._HISTORY_COUNT_;
int y = i / rh.Const._HISTORY_COUNT_;
float xl = 9.0f;
float yl = -8.0f;
GameObject o = Instantiate(prefab_big_road) as GameObject;
o.transform.SetParent(pos_big_road);
o.transform.localScale = Vector3.one; //(1,1,1)
o.transform.localPosition = new Vector3(x * xl, y * yl, 0f);
o.GetComponent<UISprite>().spriteName = array_big_road[i] == 1 ? "layout_player_bigline-01" : "layout_banker_bigline-01";
NGUITools.SetActive(o, true);
yield return new WaitForEndOfFrame();
}
yield break;
}
void DeleteChildrens(Transform t)
{
NGUITools.DestroyChildren(t);
}
public void WinLog()
{
StopCoroutine("WinLog_big_road");
StartCoroutine("WinLog_big_road");
}
}
[Serializable]
public class ExampleClass
{
public string dataToParse;
}
ConstantValue.cs
public const int _HISTORY_COUNT_ = 70;
public const int _HISTORY_HEIGHT_ = 6;
PlayInfo.cs
public int[] _BIG_ROAD_ = new int[Const._HISTORY_COUNT_ * Const._HISTORY_HEIGHT_ ];
What i am trying to achieve here is that see image
my jsonString="[1, 1, 2, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1]"; that is converted into json format needs to do it something like this for example
1 = blue circle
2 = red circle
just like that in the picture every value on my json data needs to be instantiated with the sprite that is equivalent to 1 and 2 which is i have this condition o.GetComponent<UISprite>().spriteName = array_big_road[i] == 1 ? "layout_player_bigline-01" : "layout_banker_bigline-01";
PS: I am very sorry if i couldn't explain it very well because english is not my native so i provided a picture. I am very sorry.
EDIT: I did it like this but the problem is that it's not getting what i want all the red which is 2 is the only appearing on the board
for (int i = 1; i < obj.dataToParse.Length - 1; i += 3)
{
char indivisualChar = obj.dataToParse[i];
int j = 0;
if(j < rh.Const._HISTORY_COUNT_ * rh.Const._HISTORY_HEIGHT_)
{
//lets increment it
j++;
//instantiate the sprite
GameObject o = Instantiate(prefab_big_road) as GameObject;
o.transform.SetParent(pos_big_road);
o.transform.localScale = Vector3.one; //(1,1,1)
int x = j % rh.Const._HISTORY_COUNT_;
int y = j / rh.Const._HISTORY_COUNT_;
float xl = 9.0f;
float yl = -8.0f;
o.transform.localPosition = new Vector3(x * xl, y * yl, 0f);
//o.GetComponent<UISprite>().spriteName = indivisualChar == 1 ? "layout_player_bigline-01" : "layout_banker_bigline-01";
if (indivisualChar == 1)
{
o.GetComponent<UISprite>().spriteName = "layout_player_bigline-01";
NGUITools.SetActive(o, true);
}
else
{
o.GetComponent<UISprite>().spriteName = "layout_banker_bigline-01";
NGUITools.SetActive(o, true);
}
}
//Debug.Log(indivisualChar);
}
EDITED: More information.
It just give me this
All of the sprites are in one place and the second problem of that is all the prefab that is cloned is always red (2)
I solve the issue about all game prefab that are instantiated is all red so what at i did here was like this.
char indivisualChar = obj.dataToParse[i];
int j = 0;
if (j < rh.Const._HISTORY_COUNT_ * rh.Const._HISTORY_HEIGHT_)
{
//lets increment it
j++;
//instantiate the sprite
GameObject o = Instantiate(prefab_big_road) as GameObject;
o.transform.SetParent(pos_big_road);
o.transform.localScale = Vector3.one; //(1,1,1)
int x = j % rh.Const._HISTORY_COUNT_;
int y = j / rh.Const._HISTORY_COUNT_;
float xl = 2.0f;
float yl = -22.0f;
o.transform.localPosition = new Vector3(x * xl, y * yl, 0f);
o.GetComponent<UISprite>().spriteName = indivisualChar == '1' ? "layout_player_bigline-01" : "layout_banker_bigline-01";
NGUITools.SetActive(o, true);
}
Thanks.
I am making an automated floor plan generation desktop app. In this, at first I draw the polygon on points, using this method
public void DrawPolygonPointF(PaintEventArgs e) {
// Create pen.
Pen blackPen = new Pen(Color.Black, 3);
// Create points that define polygon.
PointF point1 = new PointF(50.0F, 50.0F);
PointF point2 = new PointF(100.0F, 25.0F);
PointF point3 = new PointF(200.0F, 5.0F);
PointF point4 = new PointF(250.0F, 50.0F);
PointF point5 = new PointF(300.0F, 100.0F);
PointF point6 = new PointF(350.0F, 200.0F);
PointF point7 = new PointF(250.0F, 250.0F);
PointF[] curvePoints =
{
point1,
point2,
point3,
point4,
point5,
point6,
point7
};
// Draw polygon curve to screen.
e.Graphics.DrawPolygon(blackPen, curvePoints);
}
NOTE: These points are not actual points, they are for only demo purpose. I am reading the points from a text file.
Now I need to generate a special type of grid.
In generating the grid the first step is detect corners and extend the corner lines.
How do I detect the corners of a polygon so can i move to next step of generating grid?
Corners are marked. I need to extend corner marked with black on horizontally left side and other one is to extend on right side till its touch the line.
A screenshot is attached.
Thanks in advance
In my understanding you are trying to extend edges, not corners.
the procedure could be:
Enumerate edges (each 2 adjacent points define an edge)
For each edge find if it vertical or horizontal (abs(x1-x2) > abs(y1-y2))
Find if edge can be extended, the horizontal (left/right) and the vertical (up/bottom)
bool CheckHorizontalExtensibilityToRight(Point[] curvePoints, Point corner)
{
return curvePoints.Any(cp=>cp.Y < corner.Y && cp.X < corner.X);
}
Try this example and see if you can adapt it to solve your problem...
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication
{
public partial class Form1 : Form
{
private struct LineSegment
{
private PointF _a, _b;
public PointF A { get { return _a; } }
public PointF B { get { return _b; } }
public LineSegment(PointF a, PointF b)
{
_a = a; _b = b;
}
public float GetLengthSquared()
{
var dx = _a.X - _b.X;
var dy = _a.Y - _b.Y;
return dx * dx + dy * dy;
}
public bool RectContains(PointF a)
{
var x = a.X;
var y = a.Y;
var x1 = _a.X;
var y1 = _a.Y;
var x2 = _b.X;
var y2 = _b.Y;
return (x1 < x2 ? x1 <= x && x2 >= x : x2 <= x && x1 >= x) && (y1 < y2 ? y1 <= y && y2 >= y : y2 <= y && y1 >= y);
}
public bool ExtendToIntersectWith(LineSegment b)
{
var x1 = _a.X;
var y1 = _a.Y;
var x2 = _b.X;
var y2 = _b.Y;
var x3 = b._a.X;
var y3 = b._a.Y;
var x4 = b._b.X;
var y4 = b._b.Y;
var a1 = y2 - y1;
var b1 = x1 - x2;
var c1 = x1 * y2 - x2 * y1;
var a2 = y4 - y3;
var b2 = x3 - x4;
var c2 = x3 * y4 - x4 * y3;
var d = a1 * b2 - b1 * a2;
if (d == 0)
return false;
var x = (c1 * b2 - b1 * c2) / d;
var y = (a1 * c2 - c1 * a2) / d;
var p = new PointF(x, y);
if (b.RectContains(p) && !RectContains(p))
{
if (new LineSegment(_a, p).GetLengthSquared() < new LineSegment(_b, p).GetLengthSquared())
_a = p;
else
_b = p;
return true;
}
return false;
}
}
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
PointF[] curvePoints =
{
/*
new PointF(50.0F, 50.0F),
new PointF(100.0F, 25.0F),
new PointF(200.0F, 5.0F),
new PointF(250.0F, 50.0F),
new PointF(300.0F, 100.0F),
new PointF(350.0F, 200.0F),
new PointF(250.0F, 250.0F)
*/
new PointF(30F, 10F),
new PointF(60F, 10F),
new PointF(60F, 20F),
new PointF(90F, 20F),
new PointF(90F, 60F),
new PointF(10F, 60F),
new PointF(10F, 40F),
new PointF(30F, 40F),
};
int n = curvePoints.Length;
LineSegment[] lineSegments = new LineSegment[n];
int i = 0;
for (; i < n - 1; ++i)
lineSegments[i] = new LineSegment(curvePoints[i], curvePoints[i + 1]);
lineSegments[i] = new LineSegment(curvePoints[i], curvePoints[0]);
for (i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
lineSegments[i].ExtendToIntersectWith(lineSegments[j]);
for (i = 0; i < n; ++i)
{
var lineSegment = lineSegments[i];
e.Graphics.DrawLine(Pens.Black, lineSegment.A, lineSegment.B);
}
//e.Graphics.DrawPolygon(Pens.Black, curvePoints);
}
}
}