Avatar billede speedy Nybegynder
26. november 2000 - 22:12 Der er 11 kommentarer og
1 løsning

Rotation af punkt i Bitmap.

Hej

Jeg vil gerne kunne rotere et punkt udfra en cirkels centrum, og cirklens radius og x antal grader. Jeg kan godt gætte mig til at det har noget med sinus & cosinus at gøre, men jeg kan ikke helt gennemtænke hvordan.

f.eks. skal punktet (10,10) roteres 90° omkring cirklen med centrum i (5,10) og radius på 5. punktet (10,10) vil nu være (5,5)

Hvordan kan dette gøres ??

/SpEeDy
Avatar billede stigc Nybegynder
26. november 2000 - 22:25 #1
Skal det altid være 90 grader eller hvad med 23,23 grader?

Avatar billede speedy Nybegynder
26. november 2000 - 22:27 #2
Det skal være en vilkårlig vinkel.

/SpEeDy
Avatar billede pellelil Nybegynder
27. november 2000 - 07:32 #3
Kig på \"Efg\'s Computer Lab\", der finder du det du søger. Jeg har selv brugt formlerne til at \"rotere nogle koordinater\": http://www.efg2.com/lab/  eller direkte link hvis du hellere vi have denne:
http://www.efg2.com/lab/ImageProcessing/RotateScanline.htm

Ud fra formlerner har jeg lavet flg. Component (til behandling af \"punkter\"). Erstat \"Float\" med \"Double\" (eller lign.):
<SNIP>
//--- Interface ---
  TFloatPoint = Class(TPersistent)
  private
    Fx        : Float;
    Fy        : Float;
    FAsCompas : Boolean;
  public
    Constructor Create(nX : Float = 0.0; nY : Float = 0.0;
                      lAsCompas : Boolean = False);
    Procedure  Assign(Source: TPersistent);  Override;
    //---
    Procedure  Translate(nX, nY : Float);
    Function    DeltaX(Point : TFloatPoint) : Float;
    Function    DeltaY(Point : TFloatPoint) : Float;
    Function    Distance(Point : TFloatPoint) : Float;
    Function    Direction(Point : TFloatPoint) : Float;
    Function    Bearing(Point : TFloatPoint) : Float;
    Procedure  RotatePoint(Point : TFloatPoint; nDegrees : Float);
    Procedure  Rotate(nDegrees : Float);
    //---
    property X : Float Read fX Write fX;
    property Y : Float Read fY Write fY;
    property AsCompas : Boolean Read FAsCompas Write FAsCompas;
  end;

//--- Implementation ---

Function    Degrees360(nDegrees : Float) : Float;
begin
  Result := nDegrees;
  While (Result >= 360) do Result := Result - 360;
  While (Result < 0) do Result := Result + 360;
end;


Function    CompasMathDegree(nDegrees : Float) : Float;
begin
  Result := Degrees360((360 - nDegrees) + 90);
end;

//---
Constructor TFloatPoint.Create(nX : Float = 0.0; nY : Float = 0.0;
                              lAsCompas : Boolean = False);
begin
  Fx        := nX;
  Fy        := nY;
  FAsCompas := lAsCompas;
end;


Procedure  TFloatPoint.Assign(Source : TPersistent);
begin
  Fx        := TFloatPoint(Source).Fx;
  Fy        := TFloatPoint(Source).Fy;
  FAsCompas := TFloatPoint(Source).FAsCompas;
end;


Procedure  TFloatPoint.Translate(nX, nY : Float);
begin
  Fx := Fx + nX;
  Fy := Fy + nY;
end;


Function    TFloatPoint.DeltaX(Point : TFloatPoint) : Float;
begin
  Result := Fx - Point.X;
end;


Function    TFloatPoint.DeltaY(Point : TFloatPoint) : Float;
begin
  Result := Fy - Point.Y;
end;


Function    TFloatPoint.Distance(Point : TFloatPoint) : Float;
var
  nX, nY : Float;
begin
  nX := DeltaX(Point);
  nY := DeltaY(Point);
  Result := Sqrt((nX*nX)+(nY*nY));
end;


Function    TFloatPoint.Direction(Point : TFloatPoint) : Float;
var
  nDeltaX  : Float;
  nDeltaY  : Float;
  nDistance : Float;
begin
  nDeltaX  := Fx - Point.X;
  nDeltaY  := Fy - Point.Y;
  nDistance := Sqrt((nDeltaX*nDeltaX)+(nDeltaY*nDeltaY));
  Result := (RadToDeg(ArcCos(Abs(nDeltaX)/nDistance)) +
            RadToDeg(ArcSin(Abs(nDeltaY)/nDistance))) / 2;
  if (nDeltaX < 0) and (nDeltaY > 0) then Result := 180 - Result;
  if (nDeltaX < 0) and (nDeltaY < 0) then Result := Result + 180;
  if (nDeltaX > 0) and (nDeltaY < 0) then Result := 360 - Result;
  if FAsCompas then Result := CompasMathDegree(Result);
end;


Function    TFloatPoint.Bearing(Point : TFloatPoint) : Float;
begin
  Result := Degrees360(360 - Direction(Point));
end;


Procedure  TFloatPoint.RotatePoint(Point : TFloatPoint; nDegrees : Float);
var
  nDeltaX  : Float;
  nDeltaY  : Float;
  nDistance : Float;
  nDegree  : Float;
begin
  nDeltaX  := Fx - Point.X;
  nDeltaY  := Fy - Point.Y;
  if (nDeltaX = 0.0) and (nDeltaY = 0.0) then Exit;  // Nothing to rotate
  nDistance := Sqrt((nDeltaX*nDeltaX)+(nDeltaY*nDeltaY));
  nDegree := (RadToDeg(ArcCos(Abs(nDeltaX)/nDistance)) +
              RadToDeg(ArcSin(Abs(nDeltaY)/nDistance))) / 2;
  if (nDeltaX < 0) and (nDeltaY > 0) then nDegree := 180 - nDegree;
  if (nDeltaX < 0) and (nDeltaY < 0) then nDegree := nDegree + 180;
  if (nDeltaX > 0) and (nDeltaY < 0) then nDegree := 360 - nDegree;
  nDegree := Degrees360(nDegree + nDegrees);
  Fx := (Cos(DegToRad(nDegree)) * nDistance) + Point.X;
  Fy := (Sin(DegToRad(nDegree)) * nDistance) + Point.Y;
end;


Procedure  TFloatPoint.Rotate(nDegrees : Float);
var
  Point : TFloatPoint;
begin
  Point := TFloatPoint.Create(0.0, 0.0);
  Point.AsCompas := AsCompas;
  RotatePoint(Point, nDegrees);
  Point.Free;
end;
</SNIP>

Jeg vil håbe at jeg har husket det hele, ellers må du sige til.
Avatar billede pellelil Nybegynder
27. november 2000 - 07:45 #4
Jeg skulle måske lige kommentere Class\'en (en smule):

\"AsCompas\" fortæller hvordan \"grad\" skal opfattes. Hvis denne er \"True\", så tages der udgangspunk i et kompas hvor 0° er Nord (eller op), 90° øst osv... Hvis den er \"False\" så tages der udgangspunkt i matematikkens verden, hvor 0° er Øst, 90° Nord, 180° Vest og 270° er Syd. Denne \"omregning\" bruges primært i forbindelse med Direction og Bearing, som henholdsvis returnere en retning til eller en retning fra et andet punkt.

For at rotere dit punkt bruger du enten methoden \"RotatePoint\" eller \"Rotate\" afhængig af om du vil rotere dit punkt omkring (0,0) eller et andet punk. F.eks. (5,10).
Avatar billede speedy Nybegynder
28. november 2000 - 08:34 #5
Tak for hjælpen.

Jeg kunne ikke helt få dit til at fungere, men udra dit kode, og udfra den side du henviste til, lavede jeg min egen RotatePoint funktion.

function TForm1.RotatePoint(Centrum, Point: TPoint; Degrees: Real): TPoint;
var
  Radius, Radianer, TempX, TempY, A: Real;
begin
  Radius := Sqrt(((Point.x - Centrum.x)*(Point.x - Centrum.x))+((Point.y - Centrum.y)*(Point.y - Centrum.y)));
  A := ArcTan((Point.y - Centrum.y)/(Point.x - Centrum.x));
  Radianer := DegToRad(-Degrees)+A;
  TempX := (Radius*Cos(Radianer)+Centrum.x);
  TempY := (Radius*Sin(Radianer)+Centrum.y);

  Result.x := Round(TempX);
  Result.y := Round(TempY);
end;


Den tager udgangspunkt i matematikken, og ikke et kompas.

Men mange tak for hjælpen.

/SpEeDy
Avatar billede delphi Nybegynder
28. november 2000 - 10:40 #6
Jeg har lige en teknisk kommentar/spørgsmål:
  Hvo\'n i alverden vil du rotere et punkt - eller hvordan vil du kunne se om punktet er roteret?  Et punkt har pr. definition ingen udbredelse.  Det nærmeste du kommer på din skærm er en (enkelt) pixel - hvorledes vil du rotere den?

lol....

Peter
Avatar billede delphi Nybegynder
28. november 2000 - 10:45 #7
Sidder lige og funderer over hvad den korrekte tekniske betegnelse er på dit problem.  Mit umiddelbart bedste bud er en \"polær forskydelse af et punkt omkring et koordinat\".

(Ordkløver - jeg ved det, men jeg har lige lidt tid i overskud....)

Peter
Avatar billede pellelil Nybegynder
28. november 2000 - 10:45 #8
delphi> Jeg vil håbe at du spørge i spøg, men for en sikkerheds skyld. Det er ikke selve pixel\'en der skal \"roteres omkring sin egen akse\" - der imod er det et spørgsmål om at rotere pixel\'ens position omkring et andet punkt (pixel).
Avatar billede delphi Nybegynder
28. november 2000 - 10:55 #9
Jeg ved det - det var for sjov (men jeg har aligevel ret - du kan ikke rotere et punkt, du kan kun forskyde det)

Delphi
Avatar billede pellelil Nybegynder
28. november 2000 - 11:04 #10
Whatever :-)
Avatar billede speedy Nybegynder
28. november 2000 - 17:37 #11
hehe :)

Det er altid rart med god tid, Gid man havde det :)

Jeg vil bare sige, at min function hedder RotatePoint ligegyldigt hvad du sige den gør :))))

/SpEeDy
Avatar billede delphi Nybegynder
29. november 2000 - 08:14 #12
;)  Rart med lidt humor....
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester