public void scaling(out double x, out double y) { double x1 = 0.0; double y1 = 0.0; double x2 = 1.0; double y2 = 1.0; Perspective t=new Perspective(this); t *= Affine.NewRotation(-rotation()); t.transform(ref x1, ref y1); t.transform(ref x2, ref y2); x = x2 - x1; y = y2 - y1; }
public iterator_x(double px, double py, double step, Perspective m) { den=(px * m.w0 + py * m.w1 + m.w2); den_step=(m.w0 * step); nom_x=(px * m.sx + py * m.shx + m.tx); nom_x_step=(step * m.sx); nom_y=(px * m.shy + py * m.sy + m.ty); nom_y_step=(step * m.shy); x=(nom_x / den); y=(nom_y / den); }
public bool is_equal(Perspective m) { return is_equal(m, affine_epsilon); }
public bool is_equal(Perspective m, double epsilon) { return agg_basics.is_equal_eps(sx, m.sx, epsilon) && agg_basics.is_equal_eps(shy, m.shy, epsilon) && agg_basics.is_equal_eps(w0, m.w0, epsilon) && agg_basics.is_equal_eps(shx, m.shx, epsilon) && agg_basics.is_equal_eps(sy, m.sy, epsilon) && agg_basics.is_equal_eps(w1, m.w1, epsilon) && agg_basics.is_equal_eps(tx, m.tx, epsilon) && agg_basics.is_equal_eps(ty, m.ty, epsilon) && agg_basics.is_equal_eps(w2, m.w2, epsilon); }
public bool is_equal(Perspective m) { return(is_equal(m, affine_epsilon)); }
public override void OnDraw(Graphics2D graphics2D) { ImageBuffer widgetsSubImage = ImageBuffer.NewSubImageReference(graphics2D.DestImage, graphics2D.GetClippingRect()); ImageClippingProxy clippingProxy = new ImageClippingProxy(widgetsSubImage); clippingProxy.clear(new RGBA_Floats(1, 1, 1)); m_ras.SetVectorClipBox(0, 0, Width, Height); Affine move = Affine.NewTranslation(10, 10); Perspective shadow_persp = new Perspective(m_shape_bounds.Left, m_shape_bounds.Bottom, m_shape_bounds.Right, m_shape_bounds.Top, m_shadow_ctrl.polygon()); IVertexSource shadow_trans; if (m_FlattenCurves.Checked) { shadow_trans = new VertexSourceApplyTransform(m_shape, shadow_persp); } else { shadow_trans = new VertexSourceApplyTransform(m_path, shadow_persp); // this will make it very smooth after the transform //shadow_trans = new conv_curve(shadow_trans); } // Render shadow m_ras.add_path(shadow_trans); ScanlineRenderer scanlineRenderer = new ScanlineRenderer(); scanlineRenderer.RenderSolid(clippingProxy, m_ras, m_sl, new RGBA_Floats(0.2, 0.3, 0).GetAsRGBA_Bytes()); // Calculate the bounding box and extend it by the blur radius RectangleDouble bbox = new RectangleDouble(); bounding_rect.bounding_rect_single(shadow_trans, 0, ref bbox); bbox.Left -= m_radius.Value; bbox.Bottom -= m_radius.Value; bbox.Right += m_radius.Value; bbox.Top += m_radius.Value; if (m_method.SelectedIndex == 1) { // The recursive blur method represents the true Gaussian Blur, // with theoretically infinite kernel. The restricted window size // results in extra influence of edge pixels. It's impossible to // solve correctly, but extending the right and top areas to another // radius value produces fair result. //------------------ bbox.Right += m_radius.Value; bbox.Top += m_radius.Value; } stopwatch.Restart(); if (m_method.SelectedIndex != 2) { // Create a new pixel renderer and attach it to the main one as a child image. // It returns true if the attachment succeeded. It fails if the rectangle // (bbox) is fully clipped. //------------------ #if SourceDepth24 ImageBuffer image2 = new ImageBuffer(new BlenderBGR()); #else ImageBuffer image2 = new ImageBuffer(new BlenderBGRA()); #endif if (image2.Attach(widgetsSubImage, (int)bbox.Left, (int)bbox.Bottom, (int)bbox.Right, (int)bbox.Top)) { // Blur it if (m_method.SelectedIndex == 0) { // More general method, but 30-40% slower. //------------------ //m_stack_blur.blur(pixf2, agg::uround(m_radius.Value)); // Faster, but bore specific. // Works only for 8 bits per channel and only with radii <= 254. //------------------ stack_blur test = new stack_blur(); test.Blur(image2, agg_basics.uround(m_radius.Value), agg_basics.uround(m_radius.Value)); } else { // True Gaussian Blur, 3-5 times slower than Stack Blur, // but still constant time of radius. Very sensitive // to precision, doubles are must here. //------------------ m_recursive_blur.blur(image2, m_radius.Value); } } } else { /* // Blur separate channels //------------------ if(m_channel_r.Checked) { typedef agg::pixfmt_alpha_blend_gray< agg::blender_gray8, agg::rendering_buffer, 3, 2> pixfmt_gray8r; pixfmt_gray8r pixf2r(m_rbuf2); if(pixf2r.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2))) { agg::stack_blur_gray8(pixf2r, agg::uround(m_radius.Value), agg::uround(m_radius.Value)); } } if(m_channel_g.Checked) { typedef agg::pixfmt_alpha_blend_gray< agg::blender_gray8, agg::rendering_buffer, 3, 1> pixfmt_gray8g; pixfmt_gray8g pixf2g(m_rbuf2); if(pixf2g.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2))) { agg::stack_blur_gray8(pixf2g, agg::uround(m_radius.Value), agg::uround(m_radius.Value)); } } if(m_channel_b.Checked) { typedef agg::pixfmt_alpha_blend_gray< agg::blender_gray8, agg::rendering_buffer, 3, 0> pixfmt_gray8b; pixfmt_gray8b pixf2b(m_rbuf2); if(pixf2b.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2))) { agg::stack_blur_gray8(pixf2b, agg::uround(m_radius.Value), agg::uround(m_radius.Value)); } } */ } double tm = stopwatch.ElapsedMilliseconds; // Render the shape itself //------------------ if (m_FlattenCurves.Checked) { m_ras.add_path(m_shape); } else { m_ras.add_path(m_path); } scanlineRenderer.RenderSolid(clippingProxy, m_ras, m_sl, new RGBA_Floats(0.6, 0.9, 0.7, 0.8).GetAsRGBA_Bytes()); graphics2D.DrawString(string.Format("{0:F2} ms", tm), 140, 30); base.OnDraw(graphics2D); }
//------------------------------------------------------------------------ public Perspective multiply_inv(Perspective m) { Perspective t = m; t.invert(); return multiply(t); }
//-------------------------------------------------------------------- public span_interpolator_persp_lerp() { m_trans_dir = new Transform.Perspective(); m_trans_inv = new Transform.Perspective(); }
//------------------------------------------------------------------------ public Perspective premultiply(Perspective b) { Perspective a = new Perspective(this); sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0; w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1; w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2; return this; }
//------------------------------------------------------------------------ public Perspective premultiply(Affine b) { Perspective a = new Perspective(this); sx = a.sx *b.sx + a.shx*b.shy; shx = a.sx *b.shx + a.shx*b.sy; tx = a.sx *b.tx + a.shx*b.ty + a.tx; shy = a.shy*b.sx + a.sy *b.shy; sy = a.shy*b.shx + a.sy *b.sy; ty = a.shy*b.tx + a.sy *b.ty + a.ty; w0 = a.w0 *b.sx + a.w1 *b.shy; w1 = a.w0 *b.shx + a.w1 *b.sy; w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2; return this; }
//------------------------------------------------------------------------ public Perspective multiply(Affine a) { Perspective b = new Perspective(this); sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; return this; }
// Invert matrix. Returns false in degenerate case public bool invert() { double d0 = sy * w2 - w1 * ty; double d1 = w0 * ty - shy * w2; double d2 = shy * w1 - w0 * sy; double d = sx * d0 + shx * d1 + tx * d2; if (d == 0.0) { sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0; return false; } d = 1.0 / d; Perspective a = new Perspective(this); sx = d * d0; shy = d * d1; w0 = d * d2; shx = d * (a.w1 * a.tx - a.shx * a.w2); sy = d * (a.sx * a.w2 - a.w0 * a.tx); w1 = d * (a.w0 * a.shx - a.sx * a.w1); tx = d * (a.shx * a.ty - a.sy * a.tx); ty = d * (a.shy * a.tx - a.sx * a.ty); w2 = d * (a.sx * a.sy - a.shy * a.shx); return true; }
//-------------------------------------- Quadrilateral transformations // The arguments are double[8] that are mapped to quadrilaterals: // x1,y1, x2,y2, x3,y3, x4,y4 public bool quad_to_quad(double[] qs, double[] qd) { Perspective p = new Perspective(); if (!quad_to_square(qs)) return false; if (!p.square_to_quad(qd)) return false; multiply(p); return true; }
// From trans_perspective public Perspective(Perspective a) { sx = (a.sx); shy = (a.shy); w0 = a.w0; shx = (a.shx); sy = (a.sy); w1 = a.w1; tx = (a.tx); ty = (a.ty); w2 = a.w2; }
//------------------------------------------------------------------------ public Perspective premultiply_inv(Perspective m) { Perspective t = m; t.invert(); Set(t.multiply(this)); return this; }
public void Set(Perspective Other) { sx = Other.sx; shy = Other.shy; w0 = Other.w0; shx = Other.shx; sy = Other.sy; w1 = Other.w1; tx = Other.tx; ty = Other.ty; w2 = Other.w2; }
// Multiply inverse of "m" by "this" and assign the result to "this" public Perspective premultiply_inv(Affine m) { Perspective t=new Perspective(m); t.invert(); Set(t.multiply(this)); return this; }
//-------------------------------------------------------------------- public span_interpolator_persp_lerp() { m_trans_dir = new Transform.Perspective(); m_trans_inv = new Transform.Perspective(); }
// Inverse transformation of x and y. It works slow because // it explicitly inverts the matrix on every call. For massive // operations it's better to invert() the matrix and then use // direct transformations. public void inverse_transform(ref double x, ref double y) { Perspective t = new Perspective(this); if(t.invert()) t.transform(ref x, ref y); }
// From trans_perspective public Perspective(Perspective a) { sx = (a.sx); shy = (a.shy); w0 = a.w0; shx = (a.shx); sy = (a.sy); w1 = a.w1; tx = (a.tx); ty = (a.ty); w2 = a.w2; }
public override void OnDraw(Graphics2D graphics2D) { ImageBuffer widgetsSubImage = ImageBuffer.NewSubImageReference(graphics2D.DestImage, graphics2D.GetClippingRect()); IImageByte backBuffer = widgetsSubImage; if (!didInit) { didInit = true; OnInitialize(); } ImageBuffer image; if (backBuffer.BitDepth == 32) { image = new ImageBuffer(); image.Attach(backBuffer, new BlenderBGRA()); } else { if (backBuffer.BitDepth != 24) { throw new System.NotSupportedException(); } image = new ImageBuffer(); image.Attach(backBuffer, new BlenderBGR()); } ImageClippingProxy clippingProxy = new ImageClippingProxy(image); clippingProxy.clear(new RGBA_Floats(1, 1, 1)); g_rasterizer.SetVectorClipBox(0, 0, Width, Height); ScanlineRenderer scanlineRenderer = new ScanlineRenderer(); if (transformationTypeRadioButton.SelectedIndex == 0) { Bilinear tr = new Bilinear(lionShape.Bounds.Left, lionShape.Bounds.Bottom, lionShape.Bounds.Right, lionShape.Bounds.Top, quadPolygonControl.polygon()); if (tr.is_valid()) { //-------------------------- // Render transformed lion // VertexSourceApplyTransform trans = new VertexSourceApplyTransform(lionShape.Path, tr); scanlineRenderer.RenderSolidAllPaths(clippingProxy, g_rasterizer, g_scanline, trans, lionShape.Colors, lionShape.PathIndex, lionShape.NumPaths); //-------------------------- //-------------------------- // Render transformed ellipse // VertexSource.Ellipse ell = new MatterHackers.Agg.VertexSource.Ellipse((lionShape.Bounds.Left + lionShape.Bounds.Right) * 0.5, (lionShape.Bounds.Bottom + lionShape.Bounds.Top) * 0.5, (lionShape.Bounds.Right - lionShape.Bounds.Left) * 0.5, (lionShape.Bounds.Top - lionShape.Bounds.Bottom) * 0.5, 200); Stroke ell_stroke = new Stroke(ell); ell_stroke.width(3.0); VertexSourceApplyTransform trans_ell = new VertexSourceApplyTransform(ell, tr); VertexSourceApplyTransform trans_ell_stroke = new VertexSourceApplyTransform(ell_stroke, tr); g_rasterizer.add_path(trans_ell); scanlineRenderer.RenderSolid(clippingProxy, g_rasterizer, g_scanline, new RGBA_Bytes(0.5, 0.3, 0.0, 0.3)); g_rasterizer.add_path(trans_ell_stroke); scanlineRenderer.RenderSolid(clippingProxy, g_rasterizer, g_scanline, new RGBA_Bytes(0.0, 0.3, 0.2, 1.0)); } } else { Perspective tr = new Perspective(lionShape.Bounds.Left, lionShape.Bounds.Bottom, lionShape.Bounds.Right, lionShape.Bounds.Top, quadPolygonControl.polygon()); if (tr.is_valid()) { // Render transformed lion VertexSourceApplyTransform trans = new VertexSourceApplyTransform(lionShape.Path, tr); scanlineRenderer.RenderSolidAllPaths(clippingProxy, g_rasterizer, g_scanline, trans, lionShape.Colors, lionShape.PathIndex, lionShape.NumPaths); // Render transformed ellipse VertexSource.Ellipse FilledEllipse = new MatterHackers.Agg.VertexSource.Ellipse((lionShape.Bounds.Left + lionShape.Bounds.Right) * 0.5, (lionShape.Bounds.Bottom + lionShape.Bounds.Top) * 0.5, (lionShape.Bounds.Right - lionShape.Bounds.Left) * 0.5, (lionShape.Bounds.Top - lionShape.Bounds.Bottom) * 0.5, 200); Stroke EllipseOutline = new Stroke(FilledEllipse); EllipseOutline.width(3.0); VertexSourceApplyTransform TransformedFilledEllipse = new VertexSourceApplyTransform(FilledEllipse, tr); VertexSourceApplyTransform TransformedEllipesOutline = new VertexSourceApplyTransform(EllipseOutline, tr); g_rasterizer.add_path(TransformedFilledEllipse); scanlineRenderer.RenderSolid(clippingProxy, g_rasterizer, g_scanline, new RGBA_Bytes(0.5, 0.3, 0.0, 0.3)); g_rasterizer.add_path(TransformedEllipesOutline); scanlineRenderer.RenderSolid(clippingProxy, g_rasterizer, g_scanline, new RGBA_Bytes(0.0, 0.3, 0.2, 1.0)); } } //-------------------------- // Render the "quad" tool and controls g_rasterizer.add_path(quadPolygonControl); scanlineRenderer.RenderSolid(clippingProxy, g_rasterizer, g_scanline, new RGBA_Bytes(0, 0.3, 0.5, 0.6)); //m_trans_type.Render(g_rasterizer, g_scanline, clippingProxy); base.OnDraw(graphics2D); }