public void AddVertex(double x, double y, ShapePath.FlagsAndCommand cmd) { m_status = StrokeMath.status_e.initial; if (ShapePath.is_move_to(cmd)) { m_src_vertices.modify_last(new VertexDistance(x, y)); } else { if (ShapePath.is_vertex(cmd)) { m_src_vertices.add(new VertexDistance(x, y)); } else { if (ShapePath.is_end_poly(cmd)) { m_closed = (ShapePath.get_close_flag(cmd) == ShapePath.FlagsAndCommand.FlagClose); if (m_orientation == ShapePath.FlagsAndCommand.FlagNone) { m_orientation = ShapePath.get_orientation(cmd); } } } } }
// Arrange the orientation of a polygon, all polygons in a path, // or in all paths. After calling arrange_orientations() or // arrange_orientations_all_paths(), all the polygons will have // the same orientation, i.e. path_flags_cw or path_flags_ccw //-------------------------------------------------------------------- public int arrange_polygon_orientation(int start, ShapePath.FlagsAndCommand orientation) { if (orientation == ShapePath.FlagsAndCommand.FlagNone) { return(start); } // Skip all non-vertices at the beginning while (start < vertices.total_vertices() && !ShapePath.is_vertex(vertices.command(start))) { ++start; } // Skip all insignificant move_to while (start + 1 < vertices.total_vertices() && ShapePath.is_move_to(vertices.command(start)) && ShapePath.is_move_to(vertices.command(start + 1))) { ++start; } // Find the last vertex int end = start + 1; while (end < vertices.total_vertices() && !ShapePath.is_next_poly(vertices.command(end))) { ++end; } if (end - start > 2) { if (perceive_polygon_orientation(start, end) != orientation) { // Invert polygon, set orientation flag, and skip all end_poly invert_polygon(start, end); ShapePath.FlagsAndCommand PathAndFlags; while (end < vertices.total_vertices() && ShapePath.is_end_poly(PathAndFlags = vertices.command(end))) { vertices.modify_command(end++, PathAndFlags | orientation); // Path.set_orientation(cmd, orientation)); } } } return(end); }
public ShapePath.FlagsAndCommand vertex(out double x, out double y) { x = 0; y = 0; ShapePath.FlagsAndCommand command = ShapePath.FlagsAndCommand.CommandStop; bool done = false; while (!done) { switch (m_status) { case status.initial: markers.remove_all(); m_last_cmd = VertexSource.vertex(out m_start_x, out m_start_y); m_status = status.accumulate; goto case status.accumulate; case status.accumulate: if (ShapePath.is_stop(m_last_cmd)) { return(ShapePath.FlagsAndCommand.CommandStop); } generator.RemoveAll(); generator.AddVertex(m_start_x, m_start_y, ShapePath.FlagsAndCommand.CommandMoveTo); markers.add_vertex(m_start_x, m_start_y, ShapePath.FlagsAndCommand.CommandMoveTo); for (; ;) { command = VertexSource.vertex(out x, out y); //DebugFile.Print("x=" + x.ToString() + " y=" + y.ToString() + "\n"); if (ShapePath.is_vertex(command)) { m_last_cmd = command; if (ShapePath.is_move_to(command)) { m_start_x = x; m_start_y = y; break; } generator.AddVertex(x, y, command); markers.add_vertex(x, y, ShapePath.FlagsAndCommand.CommandLineTo); } else { if (ShapePath.is_stop(command)) { m_last_cmd = ShapePath.FlagsAndCommand.CommandStop; break; } if (ShapePath.is_end_poly(command)) { generator.AddVertex(x, y, command); break; } } } generator.Rewind(0); m_status = status.generate; goto case status.generate; case status.generate: command = generator.Vertex(ref x, ref y); //DebugFile.Print("x=" + x.ToString() + " y=" + y.ToString() + "\n"); if (ShapePath.is_stop(command)) { m_status = status.accumulate; break; } done = true; break; } } return(command); }
private List <Vertex> TesselateLines(List <Vector2> points, Pen p) { List <ContourVertex> vecs = new List <ContourVertex>(); List <Vertex> ret = new List <Vertex>(); if (points.Count < 2) { return(ret); } var co = color(p.Color); MatterHackers.Agg.VertexSource.PathStorage ps = new MatterHackers.Agg.VertexSource.PathStorage(); ps.remove_all(); ps.MoveTo(points[0].X, points[0].Y); for (int i = 1; i < points.Count; i++) { ps.LineTo(points[i].X, points[i].Y); } ps.end_poly(); MatterHackers.Agg.VertexSource.Stroke str = new MatterHackers.Agg.VertexSource.Stroke(ps, p.Width); switch (p.Join) { case LineJoin.Round: str.line_join(MatterHackers.Agg.VertexSource.LineJoin.Round); str.inner_join(MatterHackers.Agg.VertexSource.InnerJoin.Round); break; case LineJoin.Miter: str.line_join(MatterHackers.Agg.VertexSource.LineJoin.Miter); str.inner_join(MatterHackers.Agg.VertexSource.InnerJoin.Miter); str.inner_miter_limit(p.MiterLimit); str.miter_limit(p.MiterLimit); break; } switch (p.Cap) { case LineCaps.Butt: str.line_cap(MatterHackers.Agg.VertexSource.LineCap.Butt); break; case LineCaps.Round: str.line_cap(MatterHackers.Agg.VertexSource.LineCap.Round); break; case LineCaps.Square: str.line_cap(MatterHackers.Agg.VertexSource.LineCap.Square); break; } str.rewind(0); double x, y; LibTessDotNet.Tess t = new LibTessDotNet.Tess(); ShapePath.FlagsAndCommand cmd; do { cmd = str.vertex(out x, out y); if (ShapePath.is_vertex(cmd)) { vecs.Add(new ContourVertex() { Position = new Vec3() { X = (float)x, Y = (float)y } }); } if (ShapePath.is_end_poly(cmd)) { t.AddContour(vecs.ToArray()); vecs.Clear(); } } while (!ShapePath.is_stop(cmd)); /* * foreach (var v in vertices) * { * if (!ShapePath.is_close(v.command) && !ShapePath.is_stop(v.command)) * vecs.Add(new Vector2((float)v.position.x, (float)v.position.y)); * }*/ if (vecs.Count != 0) { t.AddContour(vecs.ToArray()); } t.Tessellate(LibTessDotNet.WindingRule.NonZero, LibTessDotNet.ElementType.Polygons, 3); for (var i = 0; i < t.ElementCount; i++) { for (var tri = 0; tri < 3; tri++) { var v = t.Vertices[t.Elements[(i * 3) + tri]].Position; ret.Add(new Vertex(v.X, v.Y, co)); } } return(ret); }