AGG 坐标转换管道(Coordinate conversion pipeline)

Coordinate conversion pipeline 坐标转换管道

坐标转换管道用于改变顶点源产生的顶点,包括坐标、命令、产生新顶点等。如对顶点进行矩阵变换、插入顶点形成虚线之类的功能。

变换矩阵(trans_affine)

在认识转换管道之前,先了解一下AGG的变换矩阵。通过顶点坐标与矩阵的运行,我们可以得到新的坐标。关于图像的矩阵运算,MSDN里 有一篇关 于GDI+矩阵运算的文章,很值得一看

头文件

#include <agg_trans_affine.h>

类型

trans_affine

成员变量

double sx,shy,shx,sy,tx,ty; 这六个变量组成一个2*3的矩阵,与坐标计算后得到一个新的坐标。比如对点(x,y)进行变换,则新的点(x',y') 为:
x' = x*sx  + y*shx + tx;
y' = x*shy + y*sy  + ty;

成员方法

void transform(double* x,double* y) const; 用上面的公式转换x,y坐标
const trans_affine& scale(double s);
const trans_affine& scale(double x,double y);
缩放
const trans_affine& rotate(double a); 旋转,弧度单位(pi/180)
const trans_affine& translate(double x,double y) 平移
trans_affine operator * (const trans_affine& m); 矩阵乘法
const trans_affine& invert(); 取反矩阵

坐标转换管道中有个叫conv_transform的 转换器,它能利用矩阵对源顶点进行变换,我们先在这里玩玩吧^_^

实验代码(基于此 处代码)

加入头文件 #include "agg_conv_transform.h"

把on_draw()方法的里从“// Vertex Source”到“// Scanline Rasterizer”之间的代码改写成:

  1. // Vertex Source
  2. agg::ellipse ell(0,50,50); //圆心在中间
  3. // Coordinate conversion pipeline
  4. agg::trans_affine mtx;
  5. mtx.scale(0.5,1); // x轴缩小到原来的一半
  6. mtx.rotate(agg::deg2rad(30)); // 旋转30度
  7. mtx.translate(100,100); // 平移100,100
  8. typedef agg::conv_transform<agg::ellipse> ell_ct_type;
  9. ell_ct_type ctell(ell,mtx); // 矩阵变换
  10. typedef agg::conv_contour<ell_ct_type> ell_cc_type;
  11. ell_cc_type ccell(ctell); // 轮廓变换
  12. typedef agg::conv_stroke<ell_cc_type> ell_cc_cs_type;
  13. ell_cc_cs_type csccell(ccell); // 转换成多义线
得到的图形是:

注:trans_affine不 仅仅用于源顶点的变换,在AGG库中有不少地方都能看到它。比如后面会讲到的线段(span)生成器,通过变换矩阵,就能够 自由变换填充于多边形之内的图案。

坐标转换管道

头文件

#include <agg_conv_stroke.h> // conv_stroke
#include <agg_conv_dash.h> // conv_dash
#include <agg_conv_marker.h> // conv_marker
#include <agg_conv_curve.h> // conv_curve
#include <agg_conv_contour.h> // conv_contour
#include <agg_conv_smooth_poly1.h> // conv_smooth_poly1.h
#include <agg_conv_bspline.h> // conv_bspline
#include <agg_conv_transform.h> // conv_transform

类型(演示程序基于基于此处代码)

template<class VertexSource,
class Markers = null_markers>
struct conv_stroke;
变成连续线
构造参数为VertexSource
width属性决定线宽。
例 程的ell_cc_cs_type csccell(ccell);
后面加上csccell.width(3);线宽就会变成3。
template<class VertexSource,
class Markers = null_markers>
struct conv_dash;
虚线
构造参数为VertexSource
用add_dash设置虚线长度和间隔
与conv_stroke套用
// Coordinate conversion pipeline
typedef agg::conv_contour<agg::ellipse> ell_cc_type;
ell_cc_type ccell(ell);

typedef agg::conv_dash<ell_cc_type> ell_cd_type;
ell_cd_type cdccell(ccell);
cdccell.add_dash(5,5);

typedef agg::conv_stroke<ell_cd_type> ell_cc_cs_type;
ell_cc_cs_type csccell(cdccell);
...
template<class MarkerLocator,
class MarkerShapes>
class conv_marker;
建立标记 请参考arrowhead示例代码
template<class VertexSource>
struct conv_contour;
轮廓变换
构造参数为VertexSource
width属性决定扩展或收缩轮廓。
例 程代码
template<class VertexSource>
struct conv_smooth_poly1_curve;
圆滑过渡多边形各顶点(贝塞尔)
构造参数为VertexSource
smooth_value属性决定圆滑度(默认为1)
例 程on_draw()方法最后加入下面代码
triangle t(100,100,50);//自定义顶点源
agg::conv_smooth_poly1_curve<triangle> cspct(t); ras.add_path(cspct); agg::render_scanlines_aa_solid( ras,sl,renb,agg::rgba8(255,0,0));

三角形就变得圆头圆脑啦^_^
template<class VertexSource>
struct conv_bspline;
圆滑过渡多义线各顶点(贝塞尔)
构造参数为VertexSource
interpolation_step属性决定步长。
例 程on_draw()方法最后加入下面代码
triangle t(100,50);
agg::conv_bspline<triangle> cspct(t);
ras.add_path(cspct);
agg::render_scanlines_aa_solid(
 ras,0));

三角形也能变得圆头圆脑
template<class VertexSource,
class Curve3 = curve3,
class Curve4 = curve4>
class conv_curve;
可识别VertexSource中的曲线信息
构造参数为VertexSource。conv_smooth_poly1_curve
就是基于它实现的。
例程里的顶点都没有曲线信息,算了,
到后面讲到文字输出时会用到它的。
template<class VertexSource,
class Transformer = trans_affine>
class conv_transform;
矩阵变换
用变换矩阵重新计算顶点位置
构造参数为VertexSource和变换矩阵
见变换矩阵一节的例子
作者:毛毛 来源:www.cppprog.com

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


什么是设计模式一套被反复使用、多数人知晓的、经过分类编目的、代码 设计经验 的总结;使用设计模式是为了 可重用 代码、让代码 更容易 被他人理解、保证代码 可靠性;设计模式使代码编制  真正工程化;设计模式使软件工程的 基石脉络, 如同大厦的结构一样;并不直接用来完成代码的编写,而是 描述 在各种不同情况下,要怎么解决问题的一种方案;能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免引
单一职责原则定义(Single Responsibility Principle,SRP)一个对象应该只包含 单一的职责,并且该职责被完整地封装在一个类中。Every  Object should have  a single responsibility, and that responsibility should be entirely encapsulated by t
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强烈推荐。原文截图*************************************************************************************************************************原文文本************
适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,它是针对软件开发中经常遇到的一些设计问题,总结出来的一套通用的解决方案。
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
迭代器模式提供了一种方法,用于遍历集合对象中的元素,而又不暴露其内部的细节。
外观模式又叫门面模式,它提供了一个统一的(高层)接口,用来访问子系统中的一群接口,使得子系统更容易使用。
单例模式(Singleton Design Pattern)保证一个类只能有一个实例,并提供一个全局访问点。
组合模式可以将对象组合成树形结构来表示“整体-部分”的层次结构,使得客户可以用一致的方式处理个别对象和对象组合。
装饰者模式能够更灵活的,动态的给对象添加其它功能,而不需要修改任何现有的底层代码。
观察者模式(Observer Design Pattern)定义了对象之间的一对多依赖,当对象状态改变的时候,所有依赖者都会自动收到通知。
代理模式为对象提供一个代理,来控制对该对象的访问。代理模式在不改变原始类代码的情况下,通过引入代理类来给原始类附加功能。
工厂模式(Factory Design Pattern)可细分为三种,分别是简单工厂,工厂方法和抽象工厂,它们都是为了更好的创建对象。
状态模式允许对象在内部状态改变时,改变它的行为,对象看起来好像改变了它的类。
命令模式将请求封装为对象,能够支持请求的排队执行、记录日志、撤销等功能。
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。 基本介绍 **意图:**在不破坏封装性的前提下,捕获一个对象的内部状态,并在该
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为
享元模式(Flyweight Pattern)(轻量级)(共享元素)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结