Lazarus

Programming => Graphics and Multimedia => Graphics => Topic started by: Weitentaaal on May 24, 2022, 12:53:51 pm

Title: Handle 3D Coordinates on a canvas
Post by: Weitentaaal on May 24, 2022, 12:53:51 pm
Hello,

so I wrote a program that can build some structures with blocks. However, I have certain problems with the return of 3D coordinates when clicking on the canvas. My predecessor who worked on this project had written a function which should calculate this. But the return values are not always correct. Could someone help me here on the hint. In the attachment is a picture. the depth level is steered with the arrows on the right side, whereby on the arrows must be clicked.

So i don't realy know how i get the correct X, Y Values out of the Canvas, because the Cubes are stretched. Also i do have my difficulties to handle resizing of the whole Building Area.

Here my current Code:
Code: Pascal  [Select][+][-]
  1.    m3D.X:= -1;
  2.    m3D.Y:= -1;
  3.    m3D.Z:= -1;
  4.    If (MbDownOnDrw) and (Assigned(NewCube) Then Begin
  5.       LastX:= MoveHist[NMoves].X;
  6.       LastY:= MoveHist[NMoves].Y;
  7.       If (LastX = 0) and (LastY = 0) Then
  8.          Exit;
  9.       // Richtung der Maus bestimmen
  10.       If (LastX > 0) And (LastY > 0) Then Begin
  11.          // Winkel der letzten Mausbewegung bestimmen
  12.          If Abs(ActuX - LastX) = 0 Then begin
  13.             Angle:= 90;
  14.          end
  15.          else begin
  16.             Angle:= arctan(Abs(ActuY - LastY) / Abs(ActuX - LastX)) * (180 / 3.141592); //Bogenmaß -> grad
  17.          End;
  18.  
  19.          If ActuX - LastX >= 0 Then begin // Bewegung nach rechts
  20.             XRicht:= 1;
  21.          end
  22.          else begin  // Bewegung nach Links
  23.             XRicht:= -1;
  24.          end;
  25.          If ActuY - LastY <= 0 Then Begin // Bewegung nach oben
  26.             YRicht:= 1;
  27.          end
  28.          else begin
  29.             YRicht:= -1;
  30.          end;
  31.  
  32.          If (XRicht = 1) and (YRicht = 1) Then begin // Winkel in Segment 1 (0h bis 3h)übernehmen
  33.             Angle:= Angle;
  34.          end
  35.          else if (XRicht = -1) and (YRicht = 1) then begin // Winkel in Segment 2 (9h bis 12h)
  36.             Angle:= 90 + (90 - Angle);
  37.          end
  38.          else if (XRicht = -1) and (YRicht = -1) then begin // Winkel in Segment 3 (6h bis 9h)
  39.             Angle:= 180 + Angle;
  40.          end
  41.          else if (XRicht = 1) and (YRicht = -1) then begin
  42.             Angle:= 270 + (90 - Angle);
  43.          end;
  44.          // Bereiche aufteilen in primär zu ändernde Achse
  45.          MausRicht:= '';
  46.          If ((Angle >= 0) And (Angle < 20)) Or ((Angle >= 340) and (Angle <= 360)) Or ((Angle >=110) and (Angle < 200)) Then begin
  47.             MausRicht:= 'X';
  48.          end
  49.          else if ((Angle >= 20) and (Angle <= 70)) Or ((Angle >= 200) and (Angle < 250)) Then begin
  50.             MausRicht:= 'Y';
  51.          end
  52.          else if ((Angle > 70) and (Angle < 110)) Or ((Angle >= 250) And (Angle < 340)) Then begin
  53.             MausRicht:= 'Z';
  54.          end;
  55.          If Mausricht = '' Then
  56.             ShowMessage('Mausrichtungswinkel kontrollieren!');
  57.       End;
  58.  
  59.       CDrw:= CoordRef(ActuX, ActuY, False);
  60.       cX:= CDrw.X;
  61.       cY:= CDrw.Y;
  62.       // auf Werkzeugfläche?
  63.       If (CDrw.X > ConstArea.X) and not IsMouseOnRubbish Then
  64.          Exit;
  65.  
  66.       If LastWkzPos.X = -1 Then begin
  67.          // erste Position im Konstruktionsfeld
  68.          // X berechnen, wobei Y im ersten Schritt in der Mitte bei -3 liegt
  69.          If BahnYFix = -1 Then
  70.             AcY:= 2
  71.          else
  72.             AcY:= BahnYFix - 1;
  73.  
  74.          AcX:= cX + AcY / 2;
  75.          AcZ:= cY + AcY / 2;
  76.       end
  77.       else begin
  78.          LastcY:= LastWkzPos.Z - LastWkzPos.Y / 2;
  79.          DeltaCy:= cY - LastcY;
  80.          Ok3DCoord:= True;
  81.  
  82.          If BahnYFix = -1 Then Begin
  83.             repeat
  84.                If MausRicht = 'Y' Then begin
  85.                   // Änderung zur neuen cY Position primär auf Y anwenden
  86.                   If DeltaCy > 0 Then
  87.                      AcY:= LastWkzPos.Y - Abs(DeltaCy) * 2
  88.                   else
  89.                   AcY:= LastWkzPos.Y + Abs(DeltaCy) * 2;
  90.  
  91.                   AcZ:= LastWkzPos.Z;
  92.  
  93.                   If (AcY < 0) or (AcY > ConstArea.Y - CubeSize) Then begin
  94.                      MausRicht:= 'Z';
  95.                   end;
  96.                end;
  97.                If MausRicht = 'Z' Then begin
  98.                   // Änderung zur neuen cY Position primär auf Z anwenden
  99.                   If DeltaCy > 0 Then
  100.                      AcZ:= LastWkzPos.Z + Abs(DeltaCy)
  101.                   else
  102.                      AcZ:= LastWkzPos.Z - Abs(DeltaCy);
  103.  
  104.                   AcY:= LastWkzPos.Y;
  105.  
  106.                   If MausRicht = 'X' Then begin
  107.                      // Änderung an neuer cY Position auf Y und Z aufteilen
  108.                      If DeltaCy > 0 Then begin
  109.                         AcZ:= LastWkzPos.Z + Abs(DeltaCy) / 3;
  110.                         AcY:= LastWkzPos.Y - Abs(DeltaCy) / 3 * 2;
  111.                      end
  112.                      else begin
  113.                         AcZ:= LastWkzPos.Z - Abs(DeltaCy) / 3;
  114.                         AcY:= LastWkzPos.Y + Abs(DeltaCy) / 3 * 2;
  115.                      end;
  116.                      Ok3DCoord:= True;
  117.                   end;
  118.  
  119.                end;
  120.                AcX:= cX + AcY / 2;
  121.             until Ok3DCoord;
  122.          end
  123.          else begin
  124.             AcY:= BahnYFix - 1;
  125.             AcZ:= cY + AcY / 2;
  126.             AcX:= cX + AcY / 2;
  127.          end;
  128.       End;
  129.       LastWkzPos.X:= AcX;
  130.       LastWkzPos.Y:= AcY;
  131.       LastWkzPos.Z:= AcZ;
  132.       // Aus AcX, AcY und AcZ TcX und TcY berechnen
  133.       If BahnYFix <> -1 Then begin
  134.          TcX:= AcX - AcY / 2;
  135.          If TcX <> cX Then
  136.             AcX:= cX + AcY / 2;
  137.          TcY:= AcZ - AcY / 2;
  138.          If Int(TcY * 10000) <> Int(cY * 10000) Then begin
  139.             // Y behalten und Z neu ausrechnen
  140.             AcZ:= cY + AcY / 2;
  141.          end;
  142.       End;
  143.       // Aktuelle 3D Position des Würfels merken
  144.       m3D.X:= trunc(AcX);
  145.       m3D.Y:= trunc(AcY);
  146.       m3D.Z:= trunc(AcZ);
  147.    End;
  148.  

Title: Re: Handle 3D Coordinates on a canvas
Post by: pixel_ on June 11, 2022, 07:37:45 pm
Hi. You can create one more TImage, make it not visible, paint every cell to different color r,g,b, create one or few arrays where this colors will saved, and then, when will click, by mouse x,y you can get color from invisible TImage, then find this color in array, index of color in array will equal index of cell.
TinyPortal © 2005-2018