//TODO: Split into different files private void OnMouseUp() { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { Transform objectHit = hit.transform; //Instantiate ( this.Cube, hit.point, Quaternion.identity ); var point = hit.point; Debug.Log(point.y + ", " + (point.y - 0.2f * point.y)); if (point.y > 1.4 && point.y < 1.93) { point.y -= 0.1f * point.y; } if (point.y > 1.93) { point.y -= 0.18f * point.y; } Vector3 p = new Vector3(point.x, point.y, point.z); SphericalCoord cs = CoordHelper.TransformToSphericalCoord(p, this.transform.position); Vector2 uv = CoordHelper.SphericalToUV(cs); ReadFromMap(uv); } }
private void converteData() { DataTable tempDataTable = SVCHelper.ReadCsvFile(this.path); int k = 0; foreach (DataRow row in tempDataTable.Rows) { if (!this.isStop) { k++; string xString = row["X"] != null ? row["X"].ToString() : ""; string yString = row["Y"] != null ? row["Y"].ToString() : ""; double x = 0.0, y = 0.0; double.TryParse(xString, out x); double.TryParse(yString, out y); Coord coord = new Coord(x, y); coord = CoordHelper.Gcj2Wgs(coord.lon, coord.lat); DataRow newRow = this.dataTable.NewRow(); for (int i = 0; i < row.ItemArray.Length; i++) { newRow[i] = row[i]; } newRow["WGS84_X"] = coord.lon; newRow["WGS84_Y"] = coord.lat; if (this.convertHandler != null) { this.convertHandler(newRow, k, tempDataTable.Rows.Count); } } } if (this.converteEndHandler != null) { this.converteEndHandler(); } }
public void BuildFromLandingSpot(SphericalCoord landingSpot) { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); terrainChunks = new DynamicTerrainChunk[numCols, numRows]; // Create the center chunk. Quaternion rotation = CoordHelper.SphericalToRotation(landingSpot); if (rotTest) { rotation *= Quaternion.Euler(0, 0, 45); } Vector3 position = new Vector3( (-WorldUnitsPerChunk / 2f), 0, (-WorldUnitsPerChunk / 2f) ); // FIXME: Hardcoded? terrainChunks[1, 1] = BuildChunk(rotation, position); BuildChunkArray(); //RebuildChunks(); sw.Stop(); Debug.Log("Terrain generation time: " + (sw.ElapsedMilliseconds / 1000f)); }
private void DrawCanvas_MouseMove(object sender, MouseEventArgs e) { var p = CoordHelper.TranslateFromMouse(CanvasWrapper.Config, e.GetPosition(drawCanvas).X, e.GetPosition(drawCanvas).Y); var xps = string.Format("{0:0.###}", p.ValueX); var yps = string.Format("{0:0.###}", p.ValueY); UpdateStatus("POINT: (" + xps + ", " + yps + ")"); }
void FixedUpdate() { string s = ""; s += string.Format("TRANSFORM (SPACE): {0}\n", TargetObject.position); SphericalCoord sphereCoord = CoordHelper.TransformToSphericalCoord(TargetObject.position, ParentObject.position); s += string.Format("SPHERICAL COORDINATES: {0}\n", sphereCoord.ToString()); Vector2 uvCoord = CoordHelper.SphericalToUV(sphereCoord); s += string.Format("UV COORDINATES: {0}\n", uvCoord.ToString()); text.text = s; }
public SphericalCoord LocalToSpherical(Vector3 localPosition) { // We need to know our 0..1 float xPos = localPosition.x / terrainData.size.x; float yPos = localPosition.z / terrainData.size.z; // NOTE: Z! Quaternion pointRotation = ChunkRotation * Quaternion.Euler( xPos * DegreesPerChunk - (DegreesPerChunk / 2f), yPos * DegreesPerChunk - (DegreesPerChunk / 2f), 0 ); return(CoordHelper.RotationToSpherical(pointRotation)); }
void Update() { string s = ""; s += string.Format("Transform: {0}\n", TargetObject.position); SphericalCoord sphereCoord = CoordHelper.TransformToSphericalCoord(TargetObject.position, ParentObject.position); s += string.Format("Spherical Coordinates: {0}\n", sphereCoord.ToString()); Vector2 uvCoord = CoordHelper.SphericalToUV(sphereCoord); s += string.Format("Texture UV: {0}\n", uvCoord.ToString()); text.text = s; }
private void btnBaiduPoi_Click(object sender, EventArgs e) { if (this.mapControl.extent == null) { MessageBox.Show("请选择下载区域"); return; } Extent extent = this.mapControl.extent; Extent newExtent = new Extent(); if (this.mapType == MapType.Gaode || this.mapType == MapType.GaodeImage || this.mapType == MapType.Google || this.mapType == MapType.GoogleImage) { Coord leftTop = CoordHelper.Mercator2lonLat(extent.minX, extent.minY); leftTop = CoordHelper.BdEncrypt(leftTop.lat, leftTop.lon); Coord rightBottum = CoordHelper.Mercator2lonLat(extent.maxX, extent.maxY); rightBottum = CoordHelper.BdEncrypt(rightBottum.lat, rightBottum.lon); newExtent.minX = leftTop.lon; newExtent.minY = leftTop.lat; newExtent.maxX = rightBottum.lon; newExtent.maxY = rightBottum.lat; } else if (this.mapType == MapType.Tiandi || this.mapType == MapType.TiandiImage) { Coord leftTop = CoordHelper.Transform(extent.minX, extent.minY); leftTop = CoordHelper.BdEncrypt(leftTop.lat, leftTop.lon); Coord rightBottum = CoordHelper.Transform(extent.maxX, extent.maxY); rightBottum = CoordHelper.BdEncrypt(rightBottum.lat, rightBottum.lon); newExtent.minX = leftTop.lon; newExtent.minY = leftTop.lat; newExtent.maxX = rightBottum.lon; newExtent.maxY = rightBottum.lat; } else { MessageBox.Show("该地图类型不支持兴趣点下载,选择其他类型"); return; } FrmPOIDownForBaidu frmPOIDown = new FrmPOIDownForBaidu(newExtent); frmPOIDown.Show(); }
public static void Action(NagibatorTank me, ScannedRobotEvent e) { try { if (me.IsTeammate(e.Name)) { return; } Console.WriteLine($"{nameof(OnScannedRobotModule)}: spotted [{e.Name}]. My target is [{me.Target}]"); var enemyPosition = CoordHelper.GetEnemyCoordinate(me.Heading, me.Status, e); if (string.IsNullOrWhiteSpace(me.Target)) { Console.WriteLine($"{nameof(OnScannedRobotModule)}: Setting team target {e.Name}"); me.Target = e.Name; } if (me.Target.Equals(e.Name)) { //me.SetTurnRadarRight(2.0 * Utils.NormalRelativeAngleDegrees(me.Heading + e.Bearing - me.RadarHeading)); ActionModule.Action(me); Console.WriteLine($"{nameof(OnScannedRobotModule)}: Fire to {e.Name}"); me.Fire(FireHelper.GetFirePower(me, e, enemyPosition)); MessageHelper.SendMessage(me, new Dictionary <string, string> { [Constants.MessageType] = Constants.EnemyPositionMessage.Type, [Name] = e.Name, [X] = enemyPosition.X.ToString(CultureInfo.InvariantCulture), [Y] = enemyPosition.Y.ToString(CultureInfo.InvariantCulture), [Bearing] = e.Bearing.ToString(CultureInfo.InvariantCulture), [Distance] = e.Distance.ToString(CultureInfo.InvariantCulture) }); me.TargetPoint = enemyPosition; } } catch (Exception ex) { Console.WriteLine($"{nameof(OnScannedRobotModule)}: {ex}"); } }
public void SwitchToTerrain() { if (isTerrain) { Debug.LogError("Already in terrain mode."); return; } // We are in space mode, but have to switch to terrain mode. isTerrain = true; // What are the coordinates of the ship relative to the planetoid SphericalCoord sphereCoord = CoordHelper.TransformToSphericalCoord(TheShip.position, ThePlanetoid.transform.position); string s = string.Format("Landing ship at coordinates: {0}\n", sphereCoord.ToString()); Debug.Log(s); ThePlanetoid.SetActive(false); TheTerrain.SetActive(true); // NOTE: This will freeze the game for a few seconds depending on processor speed. // Consider solutions like CoRoutines or Threading. TheTerrain.GetComponent <DynamicTerrainMaster>().BuildFromLandingSpot(sphereCoord); // Now that the terrain exists, move the ship to be in the same reference system. // Rotate the ship -90 around the X axis TheShip.transform.RotateAround(Vector3.zero, Vector3.right, -90); Vector3 pos = TheShip.transform.position; float planetRadius = ThePlanetoid.transform.localScale.x / 2f; // Pick any one axis of the scale // Subtract the radius of the planetoid pos = pos.normalized * (pos.magnitude - planetRadius); // In space, 1 unit = 1km. On ground, 1 unit = 1m. So mult scales/distance by 1000. TheShip.transform.position = pos * 1000f; Vector3 scale = TheShip.transform.localScale * 1000f; TheShip.transform.localScale = scale; }
/// <summary> /// Converts a SphericalCoord (Lat/Lon) into a Vector3 that represents /// the position of the Lat/Lon on this terrain chunk /// </summary> /// <param name="sc">Sc.</param> Vector3 SphericalToLocalPosition(SphericalCoord sc) { //Debug.Log( gameObject.name + " -- " + sc.ToString()); Quaternion buildingQat = CoordHelper.SphericalToRotation(sc); float xAngleDiff = buildingQat.eulerAngles.x - ChunkRotation.eulerAngles.x; while (xAngleDiff < -360) { xAngleDiff += 360; } while (xAngleDiff > 360) { xAngleDiff -= 360; } float yAngleDiff = buildingQat.eulerAngles.y - ChunkRotation.eulerAngles.y; //Debug.Log( gameObject.name + " -- xAngleDiff: " + xAngleDiff); //Debug.Log( gameObject.name + " -- yAngleDiff: " + yAngleDiff); Vector3 distFromCenter = new Vector3( ((yAngleDiff / DegreesPerChunk)) * WorldUnitsPerChunk, 0, // HEIGHT of building ((xAngleDiff / DegreesPerChunk)) * WorldUnitsPerChunk ); // Rotate the vector based on chunk's rotation // FIXME: I AM WRONG HERE. MAKE MATH MORE BETTER PLEASE // Do we need to incorporate longitude? I think we do. // I think we need to check the different in longitude between the center of the // terrain chunk and where the building is. distFromCenter = Quaternion.Euler(0, -ChunkRotation.eulerAngles.z, 0) * distFromCenter; // Now move the vector's origin to the bottom-left corner and return that return(distFromCenter + new Vector3(WorldUnitsPerChunk / 2, 0, WorldUnitsPerChunk / 2)); }
public void BuildFromLandingSpot(SphericalCoord landingSpot) { terrainChunks = new DynamicTerrainChunk[numCols, numRows]; // Create the center chunk. Quaternion rotation = CoordHelper.SphericalToRotation(landingSpot); //rotation *= Quaternion.Euler( 0, 0, 45 ); Vector3 position = new Vector3( (-WorldUnitsPerChunk / 2f), 0, (-WorldUnitsPerChunk / 2f) ); // FIXME: Hardcoded? terrainChunks[1, 1] = BuildChunk(rotation, position); BuildChunkArray(); //RebuildChunks(); }
void BuildStructures() { // Loop through each pixel of the structures map // if we find pixels that aren't transparent (or whatever our criteria is) // then we will spawn a structure based on the color code. Color32[] pixels = StructureMapTexture.GetPixels32(); Color32 c32 = new Color32(255, 0, 0, 255); for (int x = 0; x < StructureMapTexture.width; x++) { for (int y = 0; y < StructureMapTexture.height; y++) { Color32 p = pixels[x + y * StructureMapTexture.width]; if (p.a < 128) { // transparent pixel, ignore. continue; } Debug.Log("Not transparent!: " + p.ToString()); foreach (StructureColor sc in StructureColors) { if (sc.Color.r == p.r && sc.Color.g == p.g && sc.Color.b == p.b) { Debug.Log("Color match!"); // What is the position of the building? Quaternion quaLatLon = CoordHelper.UVToRotation(new Vector2((float)x / StructureMapTexture.width, (float)y / StructureMapTexture.height)); // Are we within DegreesPerChunk/2 of the center of the chunk, // along both direction? float xDiff = quaLatLon.eulerAngles.x - ChunkRotation.eulerAngles.x; if (xDiff > 180) { xDiff = xDiff - 360; } float yDiff = quaLatLon.eulerAngles.y - ChunkRotation.eulerAngles.y; if (yDiff > 180) { yDiff = yDiff - 360; } if (Mathf.Abs(xDiff) > DegreesPerChunk / 2f || Mathf.Abs(yDiff) > DegreesPerChunk / 2f) { // Not in our chunk! continue; } // Spawn the correct building. Vector3 pos = Vector3.zero; Quaternion rot = Quaternion.identity; GameObject theStructure = (GameObject)Instantiate(sc.StructurePrefab, pos, rot, this.transform); // Stop looping through structure colors break; // foreach } } } } }
void BuildTerrainData(TerrainData terrainData) { // Define the size of the arrays that Unity's terrain will // use internally to represent the terrain. Bigger numbers // mean more fine details. //if(CoRoutineShouldPause()) // yield return null; // "Heightmap Resolution": "Pixel resolution of the terrain’s heightmap (should be a power of two plus one, eg, 513 = 512 + 1)." // AFAIK, this defines the size of the 2-dimensional array that holds the information about the terrain (i.e. terrainData.GetHeights()) // Larger numbers lead to finer terrain details (if populated by a suitable source image heightmap). // As for actual physical size of the terrain (in Unity world space), this is defined as: // terrainData.Size = terrainData.heightmapScale * terrainData.heightmapResolution terrainData.heightmapResolution = 128 + 1; // "Base Texture Resolution": "Resolution of the composite texture used on the terrain when viewed from a distance greater than the Basemap Distance" // AFAIK, this doesn't affect the terrain mesh -- only how the terrain texture (i.e. Splats) are rendered terrainData.baseMapResolution = 512 + 1; // "Detail Resolution" and "Detail Resolution Per Patch" // (used for Details -- i.e. grass/flowers/etc...) terrainData.SetDetailResolution(1024, 32); // Set the Unity worldspace size of the terrain AFTER you set the resolution. // This effectively just sets terrainData.heightmapScale for you, depending on the value of terrainData.heightmapResolution terrainData.size = new Vector3(WorldUnitsPerChunk, TerrainHeight, WorldUnitsPerChunk); // Get the 2-dimensional array of floats that defines the actual height data for the terrain. // Each float has a value from 0..1, where a value of 1 means the maximum height of the terrain as defined by terrainData.size.y // // AFAIK, terrainData.heightmapWidth and terrainData.heightmapHeight will always be equal to terrainData.heightmapResolution // float[,] heights = terrainData.GetHeights(0, 0, terrainData.heightmapWidth, terrainData.heightmapHeight); float halfDegreesPerChunk = DegreesPerChunk / 2f; // Caching these dimensions and... int w = terrainData.heightmapWidth; int h = terrainData.heightmapHeight; // Replacing loop divisions with mults cuts this function by about 10% // -- Shout out to Karl Goodloe float widthAdjust = 1f / (w - 1f); float heightAdjust = 1f / (h - 1f); // Loop through each point in the terrainData heightmap. for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { // Normalize x and y to a value from 0..1 // NOTE: We are INVERTING the x and y because internally Unity does this float xPos = (float)x * widthAdjust; float yPos = (float)y * heightAdjust; // This converts our chunk position to a latitude/longitude, // which we can then use to get UV coordinates from the heightmap // FIXME: I think this is doing a pincushion effect // Someone smarter than me will have to figure this out. Quaternion pointRotation = ChunkRotation * Quaternion.Euler( xPos * DegreesPerChunk - halfDegreesPerChunk, yPos * DegreesPerChunk - halfDegreesPerChunk, 0 ); Vector2 uv = CoordHelper.RotationToUV(pointRotation); // Get the pixel from the heightmap image texture at the appropriate position Color pix = HeightMapTexture.GetPixelBilinear(uv.x, uv.y); // Update the heights array heights[x, y] = pix.grayscale / heightMapTextureScaling; } } // Update the terrain data based on our changed heights array terrainData.SetHeights(0, 0, heights); }
void BuildStructures() { // Loop through each pixel of the structures map // if we find pixels that aren't transparent (or whatever our criteria is) // then we will spawn a structure based on the color code. // IDEALLY -- We don't want to have to parse the building map for every chunk. // It would be nice instead if we did this once and just cached where all the // buildings should be. -- This is very easy. Color32[] pixels = StructureMapTexture.GetPixels32(); Color32 c32 = new Color32(255, 0, 0, 255); // Holy crap, it turns out that these .width and .height calls are SUUUUUUUUUPER expensive. // I cut my ENTIRE terrain-generation time in half by caching these. // -- quill18 int w = StructureMapTexture.width; int h = StructureMapTexture.height; for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { Color32 p = pixels[x + y * w]; if (p.a < 128) { // transparent pixel, ignore. continue; } //Debug.Log("Not transparent!: " + p.ToString()); foreach (StructureColor sc in StructureColors) { if (sc.Color.r == p.r && sc.Color.g == p.g && sc.Color.b == p.b) { //Debug.Log("Color match!"); // What is the position of the building? SphericalCoord buildingLatLon = CoordHelper.UVToSpherical(new Vector2((float)x / w, (float)(y) / h)); Vector3 localPosition = SphericalToLocalPosition(buildingLatLon); if (localPosition.x < 0 || localPosition.x > WorldUnitsPerChunk || localPosition.z < 0 || localPosition.z > WorldUnitsPerChunk) { // Not in our chunk! continue; } // Spawn the correct building. Vector3 globalPosition = localPosition + this.transform.position; // Fix the building's height float heightAtGlobalPosition = terrain.SampleHeight(globalPosition); globalPosition.y = heightAtGlobalPosition; // Our rotation is going to be a factor of our longitude and the Z rotation of this chunk // FIXME: Test me -- especially near the poles and with different chunk rotations Quaternion rot = Quaternion.Euler(0, ChunkRotation.eulerAngles.z + Mathf.Sin(Mathf.Deg2Rad * buildingLatLon.Latitude) * buildingLatLon.Longitude, 0); GameObject theStructure = (GameObject)Instantiate(sc.StructurePrefab, globalPosition, rot, this.transform); SmoothTerrainUnderStructure(theStructure); // Stop looping through structure colors break; // foreach } } } } }
/// <summary> /// 当地图类型选择改变时,出发,切换相应的地图 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void cmbMapTypes_SelectedIndexChanged(object sender, EventArgs e) { Coord coord = this.mapControl.GetCenter(); Coord result = coord; int oldZoom = 0; MapType oldMapType = MapType.Google; if (coord != null) { result = coord; oldZoom = this.mapControl.GetZoom(); oldMapType = this.mapType; } var selectItem = (ComboxItem)this.cmbMapType.SelectedItem; this.mapControl.setMap(selectItem.Tag.ToString()); this.mapType = (MapType)selectItem.Value; if (coord == null) { return; } switch (oldMapType) { case MapType.Baidu: case MapType.BaiduImageTile: result = CoordHelper.WebMercator2lonLat(coord); result = CoordHelper.BdDecrypt(result.lat, result.lon); result = CoordHelper.Gcj2Wgs(result.lon, result.lat); break; case MapType.Google: case MapType.GoogleImage: result = CoordHelper.WebMercator2lonLat(coord); result = CoordHelper.Gcj2Wgs(result.lon, result.lat); break; case MapType.Gaode: case MapType.GaodeImage: case MapType.QQMap: case MapType.QQImage: result = CoordHelper.WebMercator2lonLat(coord); result = CoordHelper.Gcj2Wgs(result.lon, result.lat); break; case MapType.OpenStreetMap: result = CoordHelper.WebMercator2lonLat(coord); break; case MapType.Tiandi: case MapType.TiandiImage: result = coord; break; } switch (this.mapType) { case MapType.Baidu: case MapType.BaiduImageTile: result = CoordHelper.Transform(result.lon, result.lat); result = CoordHelper.BdEncrypt(result.lat, result.lon); result = CoordHelper.WebMoctorJw2Pm(result.lon, result.lat); break; case MapType.Google: case MapType.GoogleImage: result = CoordHelper.Transform(result.lon, result.lat); result = CoordHelper.WebMoctorJw2Pm(result.lon, result.lat); break; case MapType.Gaode: case MapType.GaodeImage: case MapType.QQImage: case MapType.QQMap: result = CoordHelper.Transform(result.lon, result.lat); result = CoordHelper.WebMoctorJw2Pm(result.lon, result.lat); break; case MapType.OpenStreetMap: result = CoordHelper.WebMoctorJw2Pm(result.lon, result.lat); break; case MapType.Tiandi: case MapType.TiandiImage: break; } this.mapControl.SetZoom(oldZoom); this.mapControl.SetCenter(result); tsbClearBounds_Click(null, null); }
private void converteData() { // DataTable tempDataTable = AsposeCellsHelper.ExportToDataTable(this.path,true); //SVCHelper.readCSVFile(this.path); int k = 0; foreach (DataRow row in this.dataTable.Rows) { if (!this.isStop) { k++; DataRow newRow = row; //for (int i = 0; i < row.ItemArray.Length; i++) //{ // newRow[i] = row[i]; //} string xString = row["X"] != null ? row["X"].ToString() : "0"; string yString = row["Y"] != null ? row["Y"].ToString() : "0"; double x = 0.0, y = 0.0; double.TryParse(xString, out x); double.TryParse(yString, out y); if (x == 0 || y == 0) { continue; } Coord coord = new Coord(x, y); switch (this.covertType) { case CovertType.WGS2GCJ02: coord = CoordHelper.Transform(x, y); newRow["GDJ_X"] = coord.lon; newRow["GDJ_Y"] = coord.lat; break; case CovertType.BAIDU2GCJ02: coord = CoordHelper.BdDecrypt(y, x); newRow["GDJ_X"] = coord.lon; newRow["GDJ_Y"] = coord.lat; break; case CovertType.LONLAT2MOCTOR: coord = CoordHelper.WebMoctorJw2Pm(x, y); newRow["PM_X"] = coord.lon; newRow["PM_Y"] = coord.lat; break; case CovertType.GCJ022BAIDU: coord = CoordHelper.BdEncrypt(y, x); newRow["BD_X"] = coord.lon; newRow["BD_Y"] = coord.lat; break; case CovertType.WGS2BAIDU: coord = CoordHelper.Transform(x, y); coord = CoordHelper.BdEncrypt(coord.lat, coord.lon); newRow["BD_X"] = coord.lon; newRow["BD_Y"] = coord.lat; break; case CovertType.MOCTOR2LONLAT: coord = CoordHelper.Mercator2lonLat(x, y); newRow["JW_X"] = coord.lon; newRow["JW_Y"] = coord.lat; break; case CovertType.WGS2MOCTOR: coord = CoordHelper.Transform(x, y); coord = CoordHelper.WebMoctorJw2Pm(coord.lon, coord.lat); newRow["PM_X"] = coord.lon; newRow["PM_Y"] = coord.lat; break; } //if (this.convertHandler != null) //{ // this.convertHandler(newRow, k, tempDataTable.Rows.Count); //} } } AsposeCellsHelper.ExportToExcel(this.dataTable, this.outPutPath + "\\" + this.outputFileName); if (this.converteEndHandler != null) { this.converteEndHandler(); } }
private void DrawCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { CanvasPoint p = CoordHelper.TranslateFromMouse(CanvasWrapper.Config, e.GetPosition(drawCanvas).X, e.GetPosition(drawCanvas).Y); if (activeMode == TOOL_MODE_POINT) { EventBus.Publish(new InputPointSelected(p.DotIndexLeft, p.DotIndexTop, p.ValueX, p.ValueY)); CanvasWrapper.AddInputPoint(p.DotIndexLeft, p.DotIndexTop, p.ValueX, p.ValueY); demo.Points.Add(new Vector { X = p.ValueX, Y = p.ValueY, Alternates = new CanvasPoint { DotIndexLeft = p.DotIndexLeft, DotIndexTop = p.DotIndexTop } }); return; } if (activeMode == TOOL_MODE_LINE) { if (pointsSelected == 0) { point1_xi = p.DotIndexLeft; point1_yi = p.DotIndexTop; pointsSelected++; } else if (pointsSelected == 1) { pointsSelected++; point2_xi = p.DotIndexLeft; point2_yi = p.DotIndexTop; CompleteLine(); } } if (activeMode == TOOL_MODE_POLYGON) { if (pointsSelected == 0) { point1_xi = p.DotIndexLeft; point1_yi = p.DotIndexTop; pointsSelected++; } else if (pointsSelected == 1) { pointsSelected++; point2_xi = p.DotIndexLeft; point2_yi = p.DotIndexTop; AddPolygonLine(); } else if (pointsSelected >= 2) { pointsSelected++; // last end point becomes new start point point1_xi = point2_xi; point1_yi = point2_yi; point2_xi = p.DotIndexLeft; point2_yi = p.DotIndexTop; AddPolygonLine(); } } }