2009-12-12 10 views
13

Próbuję utworzyć funkcję przyciągania do siatki, która będzie używana w czasie wykonywania, ale mam problemy z częścią przyciągania. Udało mi się narysować kropkowaną siatkę na panelu, ale kiedy dodaję panel kontrolny do panelu, w jaki sposób mogę przyciągnąć górny lewy róg etykiety do najbliższej kropki?C# Utwórz funkcję przyciągania do siatki

Dzięki

Odpowiedz

17

pos.x - pos.x% gridWidth powinien zrobić to

+1

Dziękuję bardzo! – Nathan

+1

Pamiętaj, że powyższy kod zostanie przyciągnięty do linii siatki bliżej zera. Aby wykonać skok w lewo lub w prawo, można np. Przetestować liczbę pos.x% siatki Szerokość jest mniejsza lub równa wartości Siatka/2. Pamiętaj, że otrzymasz inny przypadek dla współrzędnych poniżej zera. To powinno dać ci wszystkie potrzebne narzędzia. – Pedery

+1

jeśli masz gridWidth = 3. dla punktuX = 5, mapuje on na 3, kiedy powinien mapować na 6. zobacz moją odpowiedź na bardziej rozbudowaną odpowiedź. –

0

Wystarczy użyć liczb całkowitych i podział będzie po prostu pracować dla Ciebie:

int xSnap = (xMouse/gridWidth) * gridWidth; 
int ySnap = (yMouse/gridHeight) * gridHeight; 

wyjątkiem oczywiście rozwiązanie modulo jest o wiele bardziej elegancko.

+0

Powielanie i dzielenie przez gridWidth. Spowoduje to ich anulowanie, pozostawiając to na zawsze równym xMouse. – Julian

+2

-1: jak @Julian powiedział, elementarna matematyka pokazuje, że ta odpowiedź jest nonsensem – ssc

1
private enum SnapMode { Create, Move } 
private Size gridSizeModeCreate = new Size(30, 30); 
private Size gridSizeModeMove = new Size(15, 15); 

private Point SnapCalculate(Point p, Size s) 
{ 
    double snapX = p.X + ((Math.Round(p.X/s.Width) - p.X/s.Width) * s.Width); 
    double snapY = p.Y + ((Math.Round(p.Y/s.Height) - p.Y/s.Height) * s.Height); 
    return new Point(snapX, snapY); 
} 

private Point SnapToGrid(Point p, SnapMode mode) 
{ 
    if (mode == SnapMode.Create) 
     return SnapCalculate(p, gridSizeModeCreate); 
    else if (mode == SnapMode.Move) 
     return SnapCalculate(p, gridSizeModeMove); 
    else 
     return new Point(0, 0); 
} 
3

Oto rozwiązanie, które rundy do najbliższego punktu siatki:

public static readonly Size Grid  = new Size(16, 16); 
    public static readonly Size HalfGrid = new Size(Grid.Width/2, Grid.Height/2); 

    // ~~~~ Round to nearest Grid point ~~~~ 
    public Point SnapCalculate(Point p) 
    { 
     int  snapX = ((p.X + HalfGrid.Width )/Grid.Width ) * Grid.Width; 
     int  snapY = ((p.Y + HalfGrid.Height)/Grid.Height) * Grid.Height; 

     return new Point(snapX, snapY); 
    } 
1

Ten działa lepiej dla mnie, ponieważ przesuwa punkt w zależności od tego, jak blisko jest do następnego lub poprzedniego spinający -point:

  if (pt.X % gridWidth < gridWidth/2) 
       pt.X = pt.X - pt.X % gridWidth; 
      else 
       pt.X = pt.X + (gridWidth - pt.X % gridWidth); 

      if (pt.Y % gridHeight < gridHeight/2) 
       pt.Y = pt.Y - pt.Y % gridHeight; 
      else 
       pt.Y = pt.Y + (gridHeight - pt.Y % gridHeight); 
14

Nie sądzę, że zaakceptowana odpowiedź jest poprawna. Oto dlaczego:

jeśli gridwidth = 3, punkt na 4 x jak należy mapować do 3, ale x = 5 powinna map do 6. Za odpowiedź Pedery na mapie będą one zarówno do 3.

dla prawidłowego Wynik należy zaokrąglić w ten sposób (można użyć wartości zmiennoprzecinkowej, jeśli punkty są ułamkami):

// Powiedzmy.

int gridCubeWidth = 3; 
int gridCubeHeight = 3; 

int newX = Math.Round(oldX/gridCubeWidth) * gridCubeWidth; 
int newY = Math.Round(oldY/gridCubeHeight) * gridCubeHeight; 
Powiązane problemy