Solved

Opinions on best way to do this...

Posted on 2004-03-30
13
195 Views
Last Modified: 2010-04-05
Hey gang,

I'm creating an application that will accompany a board game that some friends and I play.  Basically the application is to keep track of our map movements.

I have a HUGE image that has territories on it.  I want to be able to color those territories based on who owns them.  I had originally intended to do this via the web and just use HTML but it turned into a larger task and I think it requires an application of its own.  

My question is, what is the best way to individually color each territory.  Do I need to "cut" each territory into its own image, or is there a way I can overlay a color for that specific territory?  

Each map segment (territory) can be any random shape, sort of like the board game RISK.  Plus there can be hundreds of them..  A way to individually color them without having to resort to creating a colored image for each would be nice..

Thoughts?  Did I explain what I want well enough?

I use Delphi 5 btw..

Thanks guys.
0
Comment
Question by:Palamedes
  • 5
  • 4
  • 3
  • +1
13 Comments
 
LVL 17

Expert Comment

by:mokule
ID: 10717609
Use
windows.CreatePolygonRgn
0
 
LVL 17

Expert Comment

by:mokule
ID: 10717653
Here is an example of painting
procedure TForm1.MOPaintBox1Paint(Sender: TObject);
var
  dc: HDC;
  br: HBRUSH;
  Index: integer;
  hr: HRGN;
  x,y: integer;
begin
  dc := MOPaintBox1.Canvas.Handle;
  if not bEmptyRgn then
    begin
    hr := CreateRectRgn(0,0,MOPaintBox1.Width,MOPaintBox1.Height);
    CombineRgn(hr,hr,hrd,RGN_DIFF);
    SelectClipRgn(dc,hr);
    end;
  MOPaintBox1.Canvas.Draw(0,0,imFoto.Picture.Graphic);

  SelectClipRgn(dc,hrd);
  if not bEmptyRgn then
    begin
    Index := ListBox1.ItemIndex;
    if Index >= 0 then
      begin
      x := 0;
      repeat
        y := 0;
        repeat
          imKostka.Canvas.Draw(x,y,TBitmap(ListBox1.Items.Objects[Index]));
          y := y + TBitmap(ListBox1.Items.Objects[Index]).Height-1;
        until y > imKostka.Picture.Height;
        x := x + TBitmap(ListBox1.Items.Objects[Index]).Width-1;
      until x > imKostka.Picture.Width;
      end;
    MOPaintBox1.Canvas.Draw(0,0,imKostka.Picture.Bitmap);
    end;
end;
0
 
LVL 17

Expert Comment

by:mokule
ID: 10717739
And region creation

procedure TForm1.MOPaintBox1MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  hr: HRGN;
begin
  Xo := X;
  Yo := Y;
  Xp := X;
  Yp := Y;
  if tbDraw.Down then
    begin
    if ssLeft in Shift then
      begin
      if bDrawLine then
        begin
        if ilPun <= MAXPUN then
          begin
          tabPun[ilPun].x := X;
          tabPun[ilPun].y := Y;
          Inc(ilPun);
          end;
        end
      else
        begin
        bDrawLine := True;
        tabPun[0].x := X;
        tabPun[0].y := Y;
        ilPun := 1;
        end;
      end;
    if ssRight in Shift then
      begin
      if ilPun > 2 then
        begin
        if bEmptyRgn then
          begin
          hrd := CreatePolygonRgn(tabPun,ilPun,ALTERNATE);
          bEmptyRgn := False;
          end
        else
          begin
          hr := CreatePolygonRgn(tabPun,ilPun,ALTERNATE);
          bEmptyUndoRgn := False;
          CombineRgn(hru,hrd,hrd,RGN_OR);
          CombineRgn(hrd,hrd,hr,RGN_OR);
          end;
        end;
      bDrawLine := False;
      ilPun := 0;
      MOPaintBox1.Invalidate;
      end;
    end;
end;
0
Enterprise Mobility and BYOD For Dummies

Like “For Dummies” books, you can read this in whatever order you choose and learn about mobility and BYOD; and how to put a competitive mobile infrastructure in place. Developed for SMBs and large enterprises alike, you will find helpful use cases, planning, and implementation.

 
LVL 11

Expert Comment

by:shaneholmes
ID: 10717792
Mokule is right, windows.CreatePolygonRgn is the way to go.

Do you plan on having one map or many?

If your maps are going to change, you might consider creating some kind of editor by which you can create your map region ploygons with.

I recommend you look at the following articles on www.delphizine.com;

Although they are not articles on painting regions, there is great information on how to create a ploygon region editor.

If you are not a member, you can create a free limited time membership.

Shane

Hot Spots: Part I
http://www.delphizine.com/features/2002/02/di200202vh_f/di200202vh_f.asp

Hot Spots: Part II
http://www.delphizine.com/features/2002/03/di200203vh_f/di200203vh_f.asp

0
 
LVL 4

Author Comment

by:Palamedes
ID: 10717852
Thanks guys.. I'll read those articles shaneholmes.

Mokule, I'm trying to use your snippets but getting all kinds of undeclared identifiers..
bEmptyRgn, hrd, imFoto, etc..

I'm guessing you pulled this from another application?
0
 
LVL 4

Author Comment

by:Palamedes
ID: 10717876
Shane,

How do I become a free limited time member to view those articles?  I don't want to have to pay if at all possible.
0
 
LVL 11

Expert Comment

by:shaneholmes
ID: 10717975
You didn't hear this from me, but a little bird once told me that all you had to do was create a psuedo account using a free email address (i.e. yahoo, hotmail, etc) - <SMILE>

shane
0
 
LVL 17

Expert Comment

by:mokule
ID: 10718115
Sorry for some mess.
Yes of course it was cut from bigger application.
0
 
LVL 4

Author Comment

by:Palamedes
ID: 10718139
Thanks Shane  =)

One thing I don't think I made clear though in my original question..

I need to be able to color the individual sections..  They map sections have wonderful detail that I don't want to completely overwrite.. I just want to be able to give them a HUE of the color that owns them.. so some sort of opacity is needed here..  
0
 
LVL 17

Expert Comment

by:mokule
ID: 10718148
Here should be declaratons.
But now I'm not sure wether cut it from the same version.
My fault


{
type TUndo = record
  Xp,Yp: integer;
  Xk,Yk: integer;
  op:
  end;
  }
const
  MAXPUN = 100;

type
  TForm1 = class(TForm)
    ImageList1: TImageList;
    Panel1: TPanel;
    ListBox1: TListBox;
    Panel2: TPanel;
    ToolBar1: TToolBar;
    tbRect: TToolButton;
    tbEllipse: TToolButton;
    ToolButton3: TToolButton;
    StatusBar1: TStatusBar;
    Panel3: TPanel;
    MOPaintBox1: TMOPaintBox;
    Splitter1: TSplitter;
    tbNew: TToolButton;
    tbOpen: TToolButton;
    tbSave: TToolButton;
    ToolButton5: TToolButton;
    tbUndo: TToolButton;
    tbErase: TToolButton;
    ToolButton8: TToolButton;
    ToolButton1: TToolButton;
    tbDraw: TToolButton;
    tbFoto: TToolButton;
    opDlg: TOpenPictureDialog;
    imFoto: TImage;
    imKostka: TImage;

    procedure MOPaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure MOPaintBox1MouseLeave(Sender: TObject);
    procedure ListBox1DrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure FormCreate(Sender: TObject);
    procedure MOPaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure MOPaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure MOPaintBox1Paint(Sender: TObject);
    procedure ListBox1Click(Sender: TObject);
    procedure tbNewClick(Sender: TObject);
    procedure tbEraseClick(Sender: TObject);
    procedure tbUndoClick(Sender: TObject);
    procedure tbFotoClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure tbDrawClick(Sender: TObject);
  private
    { Private declarations }
    bPocz: boolean;
    Xo,Yo: integer;
    Xp,Yp: integer;
    hrd: HRGN;
    hru: HRGN;
    bEmptyUndoRgn: boolean;
    bEmptyRgn: boolean;
    bDrawLine: boolean;
    tabPun: array[0..MAXPUN] of TPoint;
    ilPun: integer;
  public
    { Public declarations }
  end;
0
 
LVL 11

Expert Comment

by:shaneholmes
ID: 10718200
Right, like I said, the links only describe how to create your own editor to load your image (map), and create a polygon region of your map, which you can use in your painting algorithm

Shane
0
 
LVL 11

Expert Comment

by:shaneholmes
ID: 10718218
What I would do once you have the polygonal region of the map, is too create a algorithm which you can invert the color in that region .

Shane
0
 
LVL 2

Accepted Solution

by:
xxflip earned 125 total points
ID: 10724351
What I did was create the regions, and create a shaded area (Green, Red, Blue, Purple, Yellow, ...) of each one, depending on the player it belongs to.

here's the Unit (the bitmap for this example and a working demo can be requested from xxflip_pt@yahoo.com),


// -------------- UNIT1.PAS
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, Buttons, jpeg;

type
  TForm1 = class(TForm)
    Img: TImage;
    BitBtn1: TBitBtn;
    chRed: TCheckBox;
    chGreen: TCheckBox;
    chBlue: TCheckBox;
    Label1: TLabel;
    procedure BitBtn1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    MyRegion:hRGN;
    originalImg:TBitmap;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
Var
  Points : Array[0..4] of TPoint;
begin
  //Keep a copy of the original
  Img.Picture.LoadFromFile('aa.bmp');
  originalImg:=TBitMap.Create;
  originalImg.Assign(Img.Picture.Bitmap);
  //Define Region 1
  //There are functions to get a region from a mask image
  Points[0].X := 56;  Points[0].Y := 149;
  Points[1].X := 151; Points[1].Y := 149;
  Points[2].X := 151; Points[2].Y := 282;
  Points[3].X := 113; Points[3].Y := 282;
  Points[4].X := 56;  Points[4].Y := 227;
  MyRegion:=CreatePolygonRgn(Points,5,Winding);
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
Var
  K,L:Integer;
  P:TColor;
begin
  For K := 0 to originalImg.Width do begin
    For L := 0 to originalImg.Height do begin
      //If pixel inside region then do the shading
      If PtInRegion(MyRegion,K, L) then begin
        P := originalImg.Canvas.Pixels[K, L];
        If chRed.Checked then P := (P and $FFFF00); //Red
        If chGreen.Checked then P := (P and $FF00FF); //Green
        If chBlue.Checked then P := (P and $00FFFF); //Blue
        Img.Canvas.Pixels[K, L] := P;
      end;
    end;
  end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  originalImg.Free;
end;

end.


// -------------- UNIT1.DFM
object Form1: TForm1
  Left = 217
  Top = 106
  Width = 597
  Height = 381
  Caption = 'Region Shades'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnClose = FormClose
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object Img: TImage
    Left = 5
    Top = 5
    Width = 463
    Height = 342
  end
  object Label1: TLabel
    Left = 475
    Top = 100
    Width = 111
    Height = 51
    AutoSize = False
    Caption = 'Try combinations of colors to get diferent shades'
    WordWrap = True
  end
  object BitBtn1: TBitBtn
    Left = 475
    Top = 5
    Width = 111
    Height = 25
    Caption = 'Color Region'
    TabOrder = 0
    OnClick = BitBtn1Click
  end
  object chRed: TCheckBox
    Left = 480
    Top = 35
    Width = 97
    Height = 17
    Caption = 'chRed'
    Checked = True
    State = cbChecked
    TabOrder = 1
  end
  object chGreen: TCheckBox
    Left = 480
    Top = 55
    Width = 97
    Height = 17
    Caption = 'chGreen'
    TabOrder = 2
  end
  object chBlue: TCheckBox
    Left = 480
    Top = 75
    Width = 97
    Height = 17
    Caption = 'chBlue'
    TabOrder = 3
  end
end
0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Established in 1997, Technology Architects has become one of the most reputable technology solutions companies in the country. TA have been providing businesses with cost effective state-of-the-art solutions and unparalleled service that is designed…

832 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question