Textos Universitarios / Serie Docencia ________________________________________________________________________ Capítulo 6 Rectángulos, trazados, regiones y recortes En la Sección 1.2.3 presentamos la estructura Rectangle y en la Sección 3.1.2 vimos la manera de dibujar y de rellenar rectángulos. En este capítulo ahondaremos más sobre este tema, sobre el tema de trazados, cubriremos además la Clase Region y veremos algunos recortes. Un rectángulo tiene tres propiedades: un punto donde inicia, un ancho y una altura. Si queremos dibujar un rectángulo gris desde el punto (0,0) con un ancho de 22 y una altura de 22 y luego un rectángulo azul desde el punto (3,3) con un ancho de 13 y una altura de 12, lo que se muestra en la Figura 6.1 es el resultado. Figura 6.1. Un rectángulo en la pantalla 6.1 Dibujo y rellenado de Rectángulos Como ya mencionamos, en el Capitulo 3 trabajamos con el dibujo y rellenado de diferente tipo de formas, en particular los rectángulos. El primer rectángulo con el que trabajamos fue el lienzo donde fuimos agregando formas o figuras. Cuando uno pinta un rectángulo relleno haciendo uso de un pincel mediante el uso, por ejemplo, del siguiente código: Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle 243 Jenaro C. Paz ________________________________________________________________________ g.FillRectangle(new SolidBrush(Color.LightGray), bgRect); se cubre por completo el rectángulo definido por Rectangle(0,0,w1,h1) con el pincel de color especificado. Figura 6.2. Rectángulo relleno Sin embargo si uno dibuja un rectángulo con una pluma, hay que tener cuidado ya que la manera en que ésta dibuja es diferente. Una pluma, de grosor de un píxel, al dibujar una línea horizontal siempre utiliza los pixeles por debajo de ella y al dibujar una línea vertical siempre lo hace usando los pixeles a la derecha de ella. Si en el código anterior agregamos las líneas necesarias para pintar un recuadro morado de 7 pixeles alrededor del rectángulo gris, estas líneas deben de ser: Pen aPen1 = new Pen(Color.MediumPurple, 7); g.DrawRectangle(aPen1,3, 3, w1-7, h1-7); Figura 6.3. Rectángulo de ancho 7 pixeles ya que en este caso por tratarse de una pluma de grosor 7 quedarán 3 pixeles a cada lado del 4to píxel que es el central. 244 Textos Universitarios / Serie Docencia ________________________________________________________________________ A continuación hemos dibujado las cuatro esquinas del mismo rectángulo donde se ha sobrepuesto un rectángulo blanco dibujado con una pluma de ancho un píxel, al centro del recuadro morado, lo anterior es con la finalidad de hacer notar los 3 pixeles a los lados del píxel central. Figura 6.4. Rectángulos de diferente grosor y color sobrepuestos Cuando presentamos las propiedades públicas del la clase Pen vimos que una de ellas es Alignment que debe tomar un valor de la enumeración PenAlignment 6.1.1 Enumeración PenAlignment31 Requisitos Espacio de Nombres : System.Drawing.Drawing2D Especifica la alineación de un objeto Pen en relación con la línea teórica de ancho cero. 6.1.1.1 Miembros Nombre de miembro Center Inset Left Outset Descripción Especifica que el objeto Pen está centrado sobre la línea teórica. Especifica que el objeto Pen está ubicado dentro de la línea teórica. Especifica que el objeto Pen está ubicado a la izquierda de la línea que se está dibujando. Especifica que el objeto Pen está ubicado fuera de la línea 31 http://msdn2.microsoft.com/en-us/library/system.drawing.drawing2d.penalignment(VS.80).aspx Junio 3 de 2006 245 Jenaro C. Paz ________________________________________________________________________ que se está dibujando. Right Especifica que el objeto Pen está ubicado a la derecha de la línea que se está dibujando. Si modificamos nuestro código anterior de la siguiente manera: Pen aPen1 = new Pen(Color.MediumPurple, 7); aPen1.Alignment=PenAlignment.Inset; g.DrawRectangle(aPen1,0, 0, w1, h1); se obtiene nuevamente una imagen como la presentada en la Figura 6.3 . El valor default para PenAlignment es Center. A continuación se presenta el código de una aplicación Web que hace uso extensivo de la clase Rectangle DrawSomeRectangles.aspx.cs private void btnGenerar_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerDrawSomeRectangles.aspx?ValorH=" + recHeight + "&ValorW=" + recWidth + "'>"); Response.Write("<p><font color=red>A Set of Rectangles!</font></p>"); } ServerDrawSomeRectangles.aspx.cs using using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; System.Drawing.Drawing2D; namespace JCPGraphics { public class ServerDrawSomeRectangles : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; 246 Textos Universitarios / Serie Docencia ________________________________________________________________________ private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["ValorW"]); h1 = UInt16.Parse(Request.QueryString["ValorH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // // Create a point and a size PointF point = new PointF(17.1f, 21.4f); SizeF size = new SizeF(80.0f, 70.0f); // Create two rectangles RectangleF r1 = new RectangleF(point, size); RectangleF r2 = new RectangleF(40.2f, 40.6f, 100.5f, 100.0f); // Ceiling a rectangle Rectangle r3 = Rectangle.Ceiling(r1); // Truncate a rectangle Rectangle r4 = Rectangle.Truncate(r1); // Round a rectangle Rectangle r5 = Rectangle.Round(r2); // Draw rectangles g.DrawRectangle(Pens.Black, r3); g.FillRectangle(Brushes.Blue, r5); // Intersect a rectangle Rectangle intersectRect = Rectangle.Intersect(r3, r5); // Fill rectangle g.FillRectangle(new SolidBrush(Color.Red), intersectRect); // Inflate a rectangle Size inflateSize = new Size(0, 30); intersectRect.Inflate(inflateSize); // Draw rectangle g.DrawRectangle(Pens.White, intersectRect); // Empty rectangle and set its properties r4 = Rectangle.Empty; r4.Location = new Point(120, 100); r4.Width = 80; r4.Height = 90; g.FillRectangle(new SolidBrush(Color.Tomato), r4); // Union rectangles Rectangle unionRect = Rectangle.Union(rect4, r5); 247 Jenaro C. Paz ________________________________________________________________________ // Draw rectangle g.DrawRectangle(Pens.Green, unionRect); // Displose of objects g.Dispose(); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream, ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream ; } Web Form Designer generated code } } Figura 6.5. Rectángulos dibujados con diferente tipo de lápices y pinceles Crea el tercer rectángulo del menor tamaño posible que pueda contener los dos rectángulos para formar una unión. 248 Textos Universitarios / Serie Docencia ________________________________________________________________________ 6.2 Trazados En el Capitulo 3 revisamos los siguientes métodos: AddLine, AddRectangle, AddEllipse, AddArc, AddPolygon, AddCurve (para curvas spline cardinales) y AddBezier, todos ellos de la clase GraphicsPath que fue diseñada para la creación de una secuencia de elementos que se van a dibujar. A continuación presentamos esta clase y veremos la utilización de otros de sus métodos . 6.2.1 Clase GraphicsPath32 Requisitos Espacio de nombres: System.Drawing.Drawing2D Representa una serie de líneas y curvas conectadas. No se puede heredar esta clase. 6.2.1.1 Constructores públicos GraphicsPath (Constructor) Sobrecargado. Inicializa una nueva instancia de la clase GraphicsPath con una enumeración FillMode de Alternate. 6.2.1.2 Propiedades públicas FillMode PathData PathPoints PathTypes PointCount Obtiene o establece una enumeración FillMode que determina cómo se rellena el interior de las formas de este objeto GraphicsPath. Obtiene un objeto PathData que encapsula matrices de puntos (points) y tipos (types) para este objeto GraphicsPath. Obtiene los puntos del trazado. Obtiene los tipos de los puntos correspondientes de la matriz PathPoints. Obtiene el número de elementos de la matriz PathPoints o de la matriz PathTypes. 6.2.1.3 Métodos públicos AddArc AddBezier Sobrecargado. Agrega un arco elíptico a la figura actual. Sobrecargado. Agrega una curva Bézier 32 http://msdn2.microsoft.com/en-us/library/system.drawing.drawing2d.graphicspath(VS.80).aspx Junio 3 de 2006 249 Jenaro C. Paz ________________________________________________________________________ AddBeziers AddClosedCurve AddCurve AddEllipse AddLine AddLines AddPath AddPie AddPolygon AddRectangle AddRectangles AddString ClearMarkers Clone CloseAllFigures CloseFigure 250 cúbica a la figura actual. Sobrecargado. Agrega una secuencia de curvas Bézier cúbicas conectadas a la figura actual. Sobrecargado. Agrega una curva cerrada a este trazado. Se utiliza una curva spline cardinal porque la curva recorre todos los puntos de la matriz. Sobrecargado. Agrega una curva spline a la figura actual. Se utiliza una curva spline cardinal porque la curva recorre todos los puntos de la matriz. Sobrecargado. Agrega una elipse al trazado actual. Sobrecargado. Agrega un segmento de línea a este objeto GraphicsPath. Sobrecargado. Agrega una serie de segmentos de línea conectados al final de este objeto GraphicsPath. Agrega el objeto GraphicsPath especificado a este trazado. Sobrecargado. Agrega el contorno de una forma circular a este trazado. Sobrecargado. Agrega un polígono a este trazado. Sobrecargado. Agrega un rectángulo a este trazado. Sobrecargado. Agrega una serie de rectángulos a este trazado. Sobrecargado. Agrega una cadena de texto a este trazado. Borra todos los marcadores de este trazado. Crea una copia exacta de este trazado. Cierra todas las figuras abiertas de este trazado e inicia una nueva figura. Cierra cada figura abierta conectando una línea desde su punto final hasta su punto inicial. Cierra la figura actual e inicia una nueva figura. Si la figura actual contiene una secuencia de líneas y curvas interconectadas, este método cierra el bucle conectando una línea desde el punto final hasta el punto inicial. Textos Universitarios / Serie Docencia ________________________________________________________________________ CreateObjRef (se hereda de MarshalByRefObject) Dispose Equals (se hereda de Object) Flatten GetBounds GetHashCode (se hereda de Object) GetLastPoint GetLifetimeService (se hereda de MarshalByRefObject) GetType (se hereda de Object) InitializeLifetimeService (se hereda de MarshalByRefObject) IsOutlineVisible IsVisible Reset Reverse SetMarkers StartFigure Crea un objeto que contiene toda la información relevante necesaria para generar un proxy utilizado para comunicarse con un objeto remoto. Libera todos los recursos utilizados por este objeto GraphicsPath. Sobrecargado. Determina si dos instancias de Object son iguales. Sobrecargado. Convierte cada una de las curvas de este trazado en una secuencia de segmentos conectados. Sobrecargado. Devuelve un rectángulo que delimita este objeto GraphicsPath. Sirve como función hash para un tipo concreto, apropiado para su utilización en algoritmos de hash y estructuras de datos como las tablas hash. Obtiene el último punto de la matriz PathPoints de este objeto GraphicsPath. Recupera el objeto de servicio de duración actual que controla la directiva de duración de esta instancia. Obtiene el objeto Type de la instancia actual. Obtiene un objeto de servicio de duración para controlar la directiva de duración de esta instancia. Sobrecargado. Indica si el punto especificado está contenido dentro (bajo) del contorno de este objeto GraphicsPath cuando se dibuja con el objeto Pen especificado. Sobrecargado. Indica si el punto especificado está dentro de este objeto GraphicsPath. Vacía las matrices PathPoints y PathTypes y establece FillMode en Alternate. Invierte el orden de puntos de la matriz PathPoints de este objeto GraphicsPath. Establece un marcador en este objeto GraphicsPath. Inicia una nueva figura sin cerrar la actual. Todos los puntos siguientes agregados al 251 Jenaro C. Paz ________________________________________________________________________ ToString (se hereda de Object) Transform Warp Widen trazado se incorporan a esta nueva figura. Devuelve un objeto String que representa al objeto Object actual. Aplica una matriz de transformación a este objeto GraphicsPath. Sobrecargado. Aplica una transformación de alabeo, definida por un rectángulo y un paralelogramo, a este objeto GraphicsPath. Sobrecargado. Reemplaza este trazado con curvas que rodean el área que está rellena cuando ese trazado se dibuja con el lápiz especificado. 6.2.1.4 Métodos protegidos Reemplazado. Vea Object.Finalize. Finalize En C# y C++, los finalizadores se expresan mediante la sintaxis del destructor. MemberwiseClone (se hereda de Object) Crea una copia superficial del objeto Object actual. GraphicsPathFlatten.aspx.cs private void { string string string btnBuild_Click(object sender, System.EventArgs e) recHeight = txtHeight.Text; recWidth = txtWidth.Text; theColor = ColorList.SelectedItem.Text ; Response.Write("<img border='0' src='ServerGraphicsPathFlatten.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "&valueC=" + theColor + "'>"+ "</p>"); } ServerGraphicsPathFlatten.aspx.cs using using using using using using using 252 System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; Textos Universitarios / Serie Docencia ________________________________________________________________________ using using using using using using using using System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; System.Drawing.Drawing2D; System.Drawing.Text; System.Globalization ; namespace JCPGraphics { public class ServerGraphicsPathFlatten: System.Web.UI.Page { int w1,h1; Color bgColor; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); bgColor=Color.FromName(Request.QueryString["valueC"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server GraphicsPath myPath = new GraphicsPath(); GraphicsPath tempPath = new GraphicsPath(); Matrix translateMatrix = new Matrix(); Matrix translateMatrix2 = new Matrix(); Matrix translateMatrix3 = new Matrix(); translateMatrix.Translate(0, 30); translateMatrix2.Translate(0, 60); translateMatrix3.Translate(0, 90); Point point1 = new Point(20, 100); Point point2 = new Point(90, 200); Point point3 = new Point(175, 10); Point point4 = new Point(245, 100); Point[] points = {point1, point2, point3, point4}; myPath.AddCurve(points); 253 Jenaro C. Paz ________________________________________________________________________ g.DrawPath(new Pen(Color.Black, 2), myPath); myPath.Flatten(translateMatrix, 10f); g.DrawPath(new Pen(Color.Red, 2), myPath); myPath.Reset(); myPath.AddCurve(points); myPath.Flatten(translateMatrix2, 20f); g.DrawPath(new Pen(Color.Green, 2), myPath); myPath.Reset(); myPath.AddCurve(points); myPath.Flatten(translateMatrix3, 30f); g.DrawPath(new Pen(Color.Blue, 2), myPath); // Dispose of object g.Dispose(); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } Web Form Designer generated code } } Figura 6.6. Uso de GraphicsPathFlatten en el dibujo de curvas 254 Textos Universitarios / Serie Docencia ________________________________________________________________________ GraphicsPathWiden.aspx.cs private void btnBuild_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; string theColor = ColorList.SelectedItem.Text ; Response.Write("<img border='0' src='ServerGraphicsPathWiden.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "&valueC=" + theColor + "'>"+ "</p>"); } ServerGraphicsPathWiden.aspx.cs using using using using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; System.Drawing.Drawing2D; System.Drawing.Text; System.Globalization ; namespace { /// /// /// JCPGraphics <summary> Summary description for rectServer. </summary> public class ServerGraphicsPathWiden: System.Web.UI.Page { int w1,h1; Color bgColor; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); bgColor=Color.FromName(Request.QueryString["valueC"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } 255 Jenaro C. Paz ________________________________________________________________________ public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server GraphicsPath myPath = new GraphicsPath(); myPath.AddEllipse(10, 10, 100, 100); myPath.AddEllipse(10, 110, 100, 100); // Draw the original ellipses to the screen in blue. g.DrawPath(Pens.Blue, myPath); // Widen the path. Pen widenPen = new Pen(Color.Blue, 10); Matrix widenMatrix = new Matrix(); widenMatrix.Translate(120, 50); myPath.Widen(widenPen, widenMatrix, 1.0f); // Draw the widened path to the screen in violet. g.FillPath(new SolidBrush(Color.Violet), myPath); // Dispose of object g.Dispose(); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } Web Form Designer generated code } } 256 Textos Universitarios / Serie Docencia ________________________________________________________________________ Figura 6.7. Uso de GraphicsPathWiden en el dibujo de figuras GraphicsPathWarp.aspx.cs private void { string string string btnBuild_Click(object sender, System.EventArgs e) recHeight = txtHeight.Text; recWidth = txtWidth.Text; theColor = ColorList.SelectedItem.Text ; Response.Write("<img border='0' src='ServerGraphicsPathWarp.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "&valueC=" + theColor + "'>"+ "</p>"); } ServerGraphicsPathWarp.aspx.cs using using using using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; System.Drawing.Drawing2D; System.Drawing.Text; System.Globalization ; namespace { /// /// /// JCPGraphics <summary> Summary description for rectServer. </summary> 257 Jenaro C. Paz ________________________________________________________________________ public class ServerGraphicsPathWarp: System.Web.UI.Page { int w1,h1; Color bgColor; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); bgColor=Color.FromName(Request.QueryString["valueC"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server GraphicsPath myPath = new GraphicsPath(); for (int i=0; i <=6; i++) { myPath.StartFigure(); // Draw Horizontal lines myPath.AddLine(20,20+16*i,212,20+16*i); myPath.StartFigure(); //Draw Vertical lines myPath.AddLine(20+32*i,20,20+32*i,116); } Pen pen1 = new Pen(Color.Blue,2); Pen pen2 = new Pen(Color.Red,2); // Draw the source path (rectangle)to the screen. g.DrawPath(pen1, myPath); // Create a destination for the warped rectangle. PointF point1 = new PointF(100, 100); PointF point2 = new PointF(300, 150); PointF point3 = new PointF(130, 200); PointF point4 = new PointF(250, 240); PointF[] destPoints = {point1, point2, point3, point4}; // Create a translation matrix. Matrix translateMatrix = new Matrix(); 258 Textos Universitarios / Serie Docencia ________________________________________________________________________ translateMatrix.Translate(60, 30); // Warp the source path (rectangle). myPath.Warp(destPoints, myPath.GetBounds(), translateMatrix, WarpMode.Perspective, 0.5f); // Draw the warped path (rectangle) to the screen. g.DrawPath(pen2, myPath); // Dispose of object g.Dispose(); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } Web Form Designer generated code } } Figura 6.8. Uso del método GraphicsPathWarp en el dibujo de rectángulos 259 Jenaro C. Paz ________________________________________________________________________ 6.2.2 Recorte con Trazados Los trazados además de servir para dibujar y rellenar, pueden usarse para recortar una region del objeto Graphics como veremos en el siguiente ejemplo GraphicsPathClipping.aspx.cs private void btnBuild_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; string theColor = ColorList.SelectedItem.Text ; Response.Write(“<img border=’0’ src=’ServerGraphicsPathClipping.aspx?valueH=” + recHeight + “&valueW=” + recWidth + “&valueC=” + theColor + “’>”+ “</p>”); } ServerGraphicsPathClipping using using using using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; System.Drawing.Drawing2D; System.Drawing.Text; System.Globalization ; namespace JCPGraphics { public class ServerGraphicsPathClipping: System.Web.UI.Page { int w1,h1; Color bgColor; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString[“valueW”]); h1 = Uint16.Parse(Request.QueryString[“valueH”]); bgColor=Color.FromName(Request.QueryString[“valueC”]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode 260 Textos Universitarios / Serie Docencia ________________________________________________________________________ memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you ffect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server GraphicsPath myPath = new GraphicsPath(); myPath.AddEllipse(0, h1/3, w1/2, h1/3); myPath.AddEllipse(w1/2, h1/3, w1/2, h1/3); myPath.AddEllipse(w1/3, 0, w1/3, h1/2); myPath.AddEllipse(w1/3, h1/2, w1/3, h1/2); g.SetClip(myPath); g.TranslateTransform(w1/2, h1/2); Pen aPen = new Pen (Color.Wheat ,2); float fRad = (float) Math.Sqrt(Math.Pow(w1/2,2) + Math.Pow(h1/2,2)); for(float fAngle =0; fAngle < (float) Math.PI * 2; fAngle +=(float)Math.PI/45) { g.DrawLine(aPen, 0,0, -fRad * (float)Math.Sin(fAngle),fRad * (float)Math.Cos(fAngle)); } // Dispose of object g.Dispose(); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } Web Form Designer generated code } } 261 Jenaro C. Paz ________________________________________________________________________ Figura 6.9. Uso del método GraphicsPathClipping en el dibujo de elipses GraphicsPathSetClip.aspx.cs private void { string string string btnBuild_Click(object sender, System.EventArgs e) recHeight = txtHeight.Text; recWidth = txtWidth.Text; theColor = ColorList.SelectedItem.Text ; Response.Write(“<img border=’0’ src=’ServerGraphicsPathSetClip.aspx?valueH=” + recHeight + “&valueW=” + recWidth + “&valueC=” + theColor + “’>”+ “</p>”); } ServerGraphicsPathSetClip.aspx.cs using using using using using using using using using using using using using using using 262 System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; System.Drawing.Drawing2D; System.Drawing.Text; System.Globalization ; Textos Universitarios / Serie Docencia ________________________________________________________________________ namespace JCPGraphics { public class ServerGraphicsPathSetClip: System.Web.UI.Page { int w1,h1; Color bgColor; private void Page_Load(object sender, System.EventArgs e) { w1 = Uint16.Parse(Request.QueryString[“valueW”]); h1 = Uint16.Parse(Request.QueryString[“valueH”]); bgColor=Color.FromName(Request.QueryString[“valueC”]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you ffect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server Bitmap imageBitmap = new Bitmap(Server.MapPath(“Textura.png”)); Brush imageBrush = new TextureBrush(imageBitmap); GraphicsPath myPath = new GraphicsPath(); myPath.AddEllipse(0, 0, w1, 2* h1/3); g.SetClip(myPath); myPath.Reset (); myPath.AddEllipse(0, h1/3, w1, 2*h1/3); //g.SetClip(myPath,CombineMode.Replace); //g.SetClip(myPath,CombineMode.Intersect); //g.SetClip(myPath,CombineMode.Union); g.SetClip(myPath,CombineMode.Xor); //g.SetClip(myPath,CombineMode.Exclude); //g.SetClip(myPath,CombineMode.Complement); g.FillRectangle(new SolidBrush(Color.Violet), bgRect); //g.FillRectangle(imageBrush, bgRect); // Dispose of object g.Dispose(); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif 263 Jenaro C. Paz ________________________________________________________________________ return aStream; } Web Form Designer generated code } } Figura 6.10. Uso del método SetClip con dos elipses Si en el código anterior comentamos y descomentamos algunas líneas como indicamos a continuación: // +++++++++++++++Begins section related with this Server Bitmap imageBitmap = new Bitmap(Server.MapPath("Textura.png")); Brush imageBrush = new TextureBrush(imageBitmap); GraphicsPath myPath = new GraphicsPath(); myPath.AddEllipse(0, 0, w1, 2* h1/3); g.SetClip(myPath); myPath.Reset (); myPath.AddEllipse(0, h1/3, w1, 2*h1/3); //g.SetClip(myPath,CombineMode.Replace); //g.SetClip(myPath,CombineMode.Intersect); //g.SetClip(myPath,CombineMode.Union); //g.SetClip(myPath,CombineMode.Xor); 264 Textos Universitarios / Serie Docencia ________________________________________________________________________ g.SetClip(myPath,CombineMode.Exclude); //g.SetClip(myPath,CombineMode.Complement); g.FillRectangle(new SolidBrush(Color.Violet), bgRect); g.FillRectangle(imageBrush, bgRect); // Dispose of object g.Dispose(); Tendremos los resultados por el modo de exclusión que se muestran en la figura: Figura 6.11. Uso de CombineMode.Exclude 6.3 Regiones Describe el interior de una forma gráfica formada por rectángulos y rutas, para trabajar con ellas, GDI+ incluye la clase Region que presentamos a continuación. 6.3.1 Clase Region33 Requisitos 33 http://msdn2.microsoft.com/en-us/library/system.drawing.region(VS.80).aspx Junio 3 de 2006 265 Jenaro C. Paz ________________________________________________________________________ Espacio de nombres: System.Drawing 6.3.1.1 Constructores públicos Region (Constructor) Sobrecargado. Inicializa un nuevo objeto Region. Existen cinco diferentes maneras de construir una región, veámoslo con ejemplos: // Creación de dos rectangulos Rectangle r1 = new Rectangle(60, 60, 80, 100); RectangleF r2 = new RectangleF(80, 120, 60, 120); // Crear una ruta GraphicsPath ruta1 = new GraphicsPath(); // Agregar rectangulo a ruta path.AddRectangle(r1); // Crear región de r1 Region rectRgn1 = new Region(r1); // Crear una región from r2 Region rectRgn2 = new Region(r2); // Crear una región from GraphicsPath Region pathRgn = new Region(ruta1); 6.3.1.2 Métodos públicos Clone Complement CreateObjRef (se hereda de MarshalByRefObject) Dispose Equals Exclude FromHrgn 266 Crea una copia exacta de este objeto Region. Sobrecargado. Actualiza este objeto Region para a la parte de la estructura RectangleF especificada que no forma una intersección con este objeto Region. Crea un objeto que contiene toda la información relevante necesaria para generar un proxy utilizado para comunicarse con un objeto remoto. Libera todos los recursos utilizados por este objeto Region. Sobrecargado. Sobrecargado. Actualiza este objeto Region a la parte de su interior que no forma una intersección con la estructura Rectangle especificada. Inicializa un nuevo objeto Region a partir Textos Universitarios / Serie Docencia ________________________________________________________________________ GetBounds GetHashCode (se hereda de Object) GetHrgn GetLifetimeService (se hereda de MarshalByRefObject) GetRegionData GetRegionScans GetType (se hereda de Object) InitializeLifetimeService (se hereda de MarshalByRefObject) Intersect IsEmpty IsInfinite IsVisible MakeEmpty MakeInfinite del identificador de una región GDI existente especificada. Obtiene una estructura RectangleF que representa un rectángulo que delimita este objeto Region en la superficie de dibujo de un objeto Graphics. Sirve como función hash para un tipo concreto, apropiado para su utilización en algoritmos de hash y estructuras de datos como las tablas hash. Devuelve un identificador de Windows de este objeto Region en el contexto de gráficos especificado. Recupera el objeto de servicio de duración actual que controla la directiva de duración de esta instancia. Devuelve un objeto RegionData que representa la información que describe este objeto Region. Devuelve una matriz de estructuras RectangleF que se aproxima a este objeto Region. Obtiene el objeto Type de la instancia actual. Obtiene un objeto de servicio de duración para controlar la directiva de duración de esta instancia. Sobrecargado. Actualiza este objeto Region a la intersección de él mismo con el objeto Region especificado. Comprueba si este objeto Region tiene el interior vacío en la superficie de dibujo especificada. Comprueba si este objeto Region tiene un interior infinito en la superficie de dibujo especificada. Sobrecargado. Comprueba si el rectángulo especificado está dentro de este objeto Region. Inicializa este objeto Region con un interior vacío. Inicializa este objeto Region con un interior 267 Jenaro C. Paz ________________________________________________________________________ infinito. ToString (se hereda de Object) Devuelve un objeto String que representa al objeto Object actual. Transform Transforma este objeto Region mediante el objeto Matrix especificado. Sobrecargado. Desplaza las coordenadas de este objeto Region en la cantidad especificada. Sobrecargado. Actualiza este objeto Region en la unión de él mismo con el objeto GraphicsPath especificado. Sobrecargado. Actualiza este objeto Region en la unión de él mismo, menos la intersección, con el objeto GraphicsPath especificado. Translate Union Xor 6.3.1.3 Métodos protegidos Reemplazado. Vea Object.Finalize. Finalize En C# y C++, los finalizadores se expresan mediante la sintaxis del destructor. MemberwiseClone (se hereda de Object) Crea una copia superficial del objeto Object actual. A continuación presentamos una aplicación Web donde se usan algunos de los métodos anteriores en la generación de gráficos en línea: RegionComplement.aspx.cs private void { string string string btnBuild_Click(object sender, System.EventArgs e) recHeight = txtHeight.Text; recWidth = txtWidth.Text; theColor = ColorList.SelectedItem.Text ; Response.Write("<img border='0' src='ServerRegionComp.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "&valueC=" + theColor + "'>"+ "</p>"); } 268 Textos Universitarios / Serie Docencia ________________________________________________________________________ ServerRegionComp.aspx.cs using using using using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; System.Drawing.Drawing2D; System.Drawing.Text; System.Globalization ; namespace JCPGraphics { public class ServerRegionComp: System.Web.UI.Page { int w1,h1; Color bgColor; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); bgColor=Color.FromName(Request.QueryString["valueC"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // Create two rectangles Rectangle r1 = new Rectangle(20, 20, 260, 280); Rectangle r2 = new Rectangle(60, 50, 260, 280); // Create two regions Region rgn1 = new Region(r1); 269 Jenaro C. Paz ________________________________________________________________________ Region rgn2 = new Region(r2); // Draw rectangles g.DrawRectangle(Pens.White, r1); g.DrawRectangle(Pens.Red, r2); // Complement can take Rectangle, RectangleF, // Region, or GraphicsPath as an argument rgn1.Complement(rgn2); // rgn1.Complement(r2); g.FillRegion(Brushes.Blue, rgn1); // Dispose of object g.Dispose(); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } Web Form Designer generated code } } Figura 6.12.Uso de regiones y RegionComplement Si vamos sustituyendo la instrucción: rgn1.Complement(rgn2); 270 Textos Universitarios / Serie Docencia ________________________________________________________________________ que involucra una llamada al metodo Complement() por cada una de las siguiente cuatro intrucciones : rgn1.Exclude(rgn2); rgn1.Union(rgn2); rgn1.Xor(rgn2); rgn1.Intersect(rgn2); que involucran a los métodos Exclude(), Union(), Xor() e Intersect(), obtendremos cada una de las cuatro siguientes imágenes. RegionExclude RegionUnion RegionXor RegionIntersect Figura 6.13. Uso de diferentes métodos de Region 6.4 Regiones y recortado Al revisar la clase Graphics en el Capítulo 3, vimos que ésta provee también métodos para el recorte de regiones de tal manera que en una aplicación se pueden restringir las regiones en donde se puede y no dibujar. Veamos a continuación como usar los métodos SetClip, ResetClip, IntersectClip, ExcludeClip y TranslateClip en las operaciones de recorte. 271 Jenaro C. Paz ________________________________________________________________________ RegionIntersectClip.aspx.cs using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; namespace JCPGraphics { /// <summary> /// Descripción breve de DibujaCuadro. /// </summary> public class RegionIntersectClip : System.Web.UI.Page { protected System.Web.UI.WebControls.TextBox txtWidth; protected System.Web.UI.WebControls.Button btnBuild; protected System.Web.UI.WebControls.DropDownList ColorList; protected System.Web.UI.WebControls.TextBox txtHeight; private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the ASP.NET Web Form Designer. // InitializeComponent(); base.OnInit(e); } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.btnBuild.Click += new System.EventHandler(this.btnBuild_Click); this.Load += new System.EventHandler(this.Page_Load); } #endregion private void btnBuild_Click(object sender, System.EventArgs 272 Textos Universitarios / Serie Docencia ________________________________________________________________________ e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; string theColor = ColorList.SelectedItem.Text ; Response.Write("<img border='0' src='ServerRegionIntersectClip.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "&valueC=" + theColor + "'>"+ "</p>"); } } } ServerRegionIntersectClip.aspx.cs using using using using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; System.Drawing.Drawing2D; System.Drawing.Text; System.Globalization ; namespace { /// /// /// JCPGraphics <summary> Summary description for rectServer. </summary> public class ServerRegionIntersectClip: System.Web.UI.Page { int w1,h1; Color bgColor; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); bgColor=Color.FromName(Request.QueryString["valueC"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); 273 Jenaro C. Paz ________________________________________________________________________ } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server g.Clear(Color.LightSteelBlue); // Create two rectangles Rectangle r1 = new Rectangle(20, 20, 260, 280); Rectangle r2 = new Rectangle(100, 100, 260, 260); // Create two regions Region rgn1 = new Region(r1); Region rgn2 = new Region(r2); // Call SetClip g.SetClip(rgn1, CombineMode.Exclude); // Call IntersectClip g.IntersectClip(rgn2); // Fill rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // Call ResetClip g.ResetClip(); // Draw rectangles g.DrawRectangle(Pens.Black, r1); g.DrawRectangle(Pens.Red, r2); // Dispose of object g.Dispose(); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the ASP.NET Web Form Designer. // InitializeComponent(); 274 Textos Universitarios / Serie Docencia ________________________________________________________________________ base.OnInit(e); } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.Load += new System.EventHandler(this.Page_Load); } #endregion } } Figura 6.14. Recortado de regiones usando ExcludeClip RegionTranslateClip.aspx.cs using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; 275 Jenaro C. Paz ________________________________________________________________________ namespace JCPGraphics { /// <summary> /// Descripción breve de DibujaCuadro. /// </summary> public class RegionTranslateClip : System.Web.UI.Page { protected System.Web.UI.WebControls.TextBox txtWidth; protected System.Web.UI.WebControls.Button btnBuild; protected System.Web.UI.WebControls.DropDownList ColorList; protected System.Web.UI.WebControls.TextBox txtHeight; private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the ASP.NET Web Form Designer. // InitializeComponent(); base.OnInit(e); } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.btnBuild.Click += new System.EventHandler(this.btnBuild_Click); this.Load += new System.EventHandler(this.Page_Load); } #endregion private void btnBuild_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; string theColor = ColorList.SelectedItem.Text ; Response.Write("<img border='0' src='ServerRegionTranslateClip.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "&valueC=" + theColor + "'>"+ "</p>"); } } 276 Textos Universitarios / Serie Docencia ________________________________________________________________________ } ServerRegionIntersectClip.aspx.cs using using using using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; System.Drawing.Drawing2D; System.Drawing.Text; System.Globalization ; namespace { /// /// /// JCPGraphics <summary> Summary description for rectServer. </summary> public class ServerRegionTranslateClip: System.Web.UI.Page { int w1,h1; Color bgColor; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); bgColor=Color.FromName(Request.QueryString["valueC"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object 277 Jenaro C. Paz ________________________________________________________________________ // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server g.Clear(Color.MediumPurple); // Create a rectangle Rectangle r1 = new Rectangle(20, 20, 200, 200); // Create a region Region rgn1 = new Region(r1); // Call SetClip g.SetClip(rgn1, CombineMode.Exclude); int a = 40; int b = 60; // Call TranslateClip g.TranslateClip(a,b); // Fill rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // Dispose of object g.Dispose(); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the ASP.NET Web Form Designer. // InitializeComponent(); base.OnInit(e); } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.Load += new System.EventHandler(this.Page_Load); } #endregion } } 278 Textos Universitarios / Serie Docencia ________________________________________________________________________ Figura 6.15 Translacion de Regiones mediante RegionTranslateClip 279 Jenaro C. Paz ________________________________________________________________________ 280