/// <summary> /// This occurs when the renderer's tool is set to clickTool. It gets the /// location of the mouseclick relative to the rederer. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void FieldViewClick(object sender, ClickedEventArgs e) { Vector2 location = e.Location; if (drawType == types.fields) { location = getNearest(location, 0.3, subFields.Values.ToList()); if (checkInside(location)) { Error inside = new Error(errorTypes.PointInside); inside.ShowDialog(); inside.Dispose(); return; } } bool intersects = false; Vector2 v1 = location - newPoly[newPoly.Count - 1]; DEASL.Core.Mathematics.Shapes.LineSegment line1 = new DEASL.Core.Mathematics.Shapes.LineSegment(location, newPoly[newPoly.Count - 1] + 0.00001 * v1); for (int i = 1; i < newPoly.Count; i++) { Vector2 temp; DEASL.Core.Mathematics.Shapes.LineSegment ls = new DEASL.Core.Mathematics. Shapes.LineSegment(newPoly[i], newPoly[i - 1]); if (ls.Intersect(line1, out temp)) { intersects = true; break; } } if (intersects) { Error intersect = new Error(errorTypes.Intersect); intersect.ShowDialog(); intersect.Dispose(); } else { newPoly.Add(location); firstPointRend.Coordinates2D = newPoly.points[0]; firstPointRend.Show = true; newPolyRend.UpdatePoints(newPoly.points); } }
/// <summary> /// When Add is clicked, it switches to Done. A popup of AddPoly appears asking for /// what type of new item is desired. Then the actual drawing is commenced. /// If one wishes to stop before finishing a object, region, or field, click Stop and /// the shape will be deleted. /// If one wishes to stop creating walls, then click Stop and that set of walls will remain. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Add_Click(object sender, EventArgs e) { if (Add.Text == "Add") //Button said add so new polygon { AddPoly popup = new AddPoly(accRobot, mainField.walls.Keys.ToList<string>(), mainField.objects.Keys.ToList<string>(), mainField.regions.Keys.ToList<string>(), subFields.Keys.ToList<string>()); popup.ShowDialog(); accRobot = popup.accRobot; if (popup.finished) { Add.Text = "Stop"; rend.Tool = polyTool; newName = popup.name; drawType = popup.drawType; Ctrl_press.Show(); } popup.Dispose(); } else //Button said Stop so stop current job. { if (drawType == types.walls && newPoly.Count > 1) { double thickness = accRobot ? robotR : wallR; mainField.addWall(newName, newPoly.points, thickness); List<Polygon> comp = new List<Polygon>(); foreach (List<Polygon> p in mainField.walls.Values) { comp.AddRange(p); } wallsRend.Polygons = comp; Walls_Box.Items.Add(newName); } else if (newPoly.Count > 2) { bool intersects = false; Vector2 v2 = newPoly[0] - newPoly[newPoly.Count - 1]; DEASL.Core.Mathematics.Shapes.LineSegment line2 = new DEASL.Core.Mathematics.Shapes. LineSegment(newPoly[0] - 0.00001 * v2, newPoly[newPoly.Count - 1] + 0.00001 * v2); for (int i = 1; i < newPoly.Count; i++) { Vector2 temp; DEASL.Core.Mathematics.Shapes.LineSegment ls = new DEASL.Core.Mathematics. Shapes.LineSegment(newPoly[i], newPoly[i - 1]); if (ls.Intersect(line2, out temp)) { intersects = true; break; } } if (intersects) { Error intersect = new Error(errorTypes.Intersect); intersect.ShowDialog(); intersect.Dispose(); } else { AddPolygon(); } } resetParameters(); Ctrl_press.Hide(); } }
/// <summary> /// Does the actuall splitting of each item. split needs to apply /// splitHelp to each individual item so easier to have a helper method. /// </summary> /// <param name="field">Shape of new Field</param> /// <param name="item">Specific item it is splitting</param> /// <returns>List of Polygons</returns> private List<Polygon> splitHelp(Polygon field, Polygon item) { List<Polygon> sub = new List<Polygon>(); Polygon itemMini = mainField.CreateThickItem(item, -0.00001); for (int i = 0; i < item.Count; i++) { Vector2[] interV = new Vector2[0]; bool A = field.IsInside(itemMini[i]); DEASL.Core.Mathematics.Shapes.LineSegment current = new DEASL.Core.Mathematics.Shapes.LineSegment(); DEASL.Core.Mathematics.Shapes.LineSegment currentMini = new DEASL.Core.Mathematics.Shapes.LineSegment(itemMini[(i + 1) % item.Count], itemMini[i]); bool B = field.DoesIntersect(currentMini); if (A) { addCorrect(sub, new Vector2[] {item[i]}, field); } bool interDifferent = false; if (B) { current = new DEASL.Core.Mathematics.Shapes.LineSegment(item[(i + 1) % item.Count], item[i]); field.Intersect(current, out interV); } if (B && A) { foreach (Vector2 v in interV) { interDifferent |= item[i].DistanceTo(v) < 0.0001 || item[(i + 1) % item.Count].DistanceTo(v) < 0.0001; } } if (B && ! interDifferent) { if (interV.Length > 1 && !current.UnitVector.ApproxEquals(new DEASL.Core.Mathematics.Shapes.LineSegment( interV[interV.Length - 1],interV[0]).UnitVector, 0.00001)) { interV = reverse(interV); } addCorrect(sub, interV, field); } } return sub; }
/// <summary> /// Adds the vectors in the correct order and to the correct polygon in addTo. Called from addCorrect. /// </summary> /// <param name="addTo">List of polygons that are collecting the split parts</param> /// <param name="addFrom">List of all vectors to add to polygon</param> /// <param name="field">Field shape</param> private void addCorrectHelp(List<Polygon> addTo, Vector2 addFrom, Polygon field) { bool addNew = true; for (int i = 0; i < addTo.Count; i++) { List<Polygon> tempPL = addTo.Select(p => new Polygon(p.points)).ToList(); addNew = false; tempPL[i].Add(addFrom); if (tempPL[i].Count == 2) { Vector2 v = tempPL[i][1] - tempPL[i][0]; DEASL.Core.Mathematics.Shapes.LineSegment line = new DEASL.Core.Mathematics.Shapes. LineSegment(tempPL[i][1] - 0.00001 * v, tempPL[i][0] + 0.00001 * v); if (field.IsInside(line)) { addTo[i].Add(addFrom); break; } } else { tempPL[i] = mainField.CreateThickItem(tempPL[i], -0.00001); bool noIntersect = true; for(int j = 0; j < tempPL[i].Count; j++) { DEASL.Core.Mathematics.Shapes.LineSegment line = new DEASL.Core.Mathematics.Shapes. LineSegment(tempPL[i][j], tempPL[i][(j + 1) % tempPL[i].Count]); if (field.DoesIntersect(line)) { noIntersect = false; break; } } if (noIntersect && field.IsInside(tempPL[i])) { addTo[i].Add(addFrom); break; } } addNew = true; } if (addNew) { addTo.Add(new Polygon(new Vector2[] { addFrom })); } }
/// <summary> /// Helper function to triangulate. /// </summary> /// <param name="poly">Polygon to breakdown</param> /// <param name="tris">List of triangles</param> /// <returns>List of triangles</returns> private List<Polygon> triangulateHelper(Polygon poly, List<Polygon> tris) { Polygon p = new Polygon(poly); if (p.Count <= 3) { tris.Add(p); return tris; } else { for (int i = 0; i < p.Count; i++) { Vector2 v = p[i+2] - p[i]; DEASL.Core.Mathematics.Shapes.LineSegment ls = new DEASL.Core.Mathematics.Shapes.LineSegment( p[i]+0.00001*v, p[i + 2]-0.00001*v); if(!p.DoesIntersect(ls) && p.IsInside(ls)) { tris.Add(new Polygon(new Vector2[] {p[i], p[i+1], p[i+2]})); p.RemoveAt(i+1); break; } } return triangulateHelper(p, tris); } }