Измените систему координат Холста в WPF

В Java все переменные, которые вы объявляете, на самом деле являются «ссылками» на объекты (или примитивы), а не самими объектами.

При попытке выполнить один метод объекта , ссылка просит живой объект выполнить этот метод. Но если ссылка ссылается на NULL (ничего, нуль, void, nada), то нет способа, которым метод будет выполнен. Тогда runtime сообщит вам об этом, выбросив исключение NullPointerException.

Ваша ссылка «указывает» на нуль, таким образом, «Null -> Pointer».

Объект живет в памяти виртуальной машины пространство и единственный способ доступа к нему - использовать ссылки this. Возьмем этот пример:

public class Some {
    private int id;
    public int getId(){
        return this.id;
    }
    public setId( int newId ) {
        this.id = newId;
    }
}

И в другом месте вашего кода:

Some reference = new Some();    // Point to a new object of type Some()
Some otherReference = null;     // Initiallly this points to NULL

reference.setId( 1 );           // Execute setId method, now private var id is 1

System.out.println( reference.getId() ); // Prints 1 to the console

otherReference = reference      // Now they both point to the only object.

reference = null;               // "reference" now point to null.

// But "otherReference" still point to the "real" object so this print 1 too...
System.out.println( otherReference.getId() );

// Guess what will happen
System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...

Это важно знать - когда больше нет ссылок на объект (в пример выше, когда reference и otherReference оба указывают на null), тогда объект «недоступен». Мы не можем работать с ним, поэтому этот объект готов к сбору мусора, и в какой-то момент VM освободит память, используемую этим объектом, и выделит другую.

18
задан Simon Sarris 5 August 2012 в 00:47
поделиться

6 ответов

Я смог добраться, это к путем создания моего собственного холста и переопределения ArrangeOverride функционирует как так:

    public class CustomCanvas : Canvas
    {
        protected override Size ArrangeOverride(Size arrangeSize)
        {
            foreach (UIElement child in InternalChildren)
            {
                double left = Canvas.GetLeft(child);
                double top = Canvas.GetTop(child);
                Point canvasPoint = ToCanvas(top, left);
                child.Arrange(new Rect(canvasPoint, child.DesiredSize));
            }
            return arrangeSize;
        }
        Point ToCanvas(double lat, double lon)
        {
            double x = this.Width / 360;
            x *= (lon - -180);
            double y = this.Height / 180;
            y *= -(lat + -90);
            return new Point(x, y);
        }
    }

, Который работает на мою описанную проблему, но она, вероятно, не работала бы на другую потребность, которую я имею, который является PathGeometry. Это не работало бы, потому что точки не определяются как Вершина и Левые, но как реальные точки.

1
ответ дан 30 November 2019 в 09:38
поделиться

Я вполне уверен, Вы не можете сделать этого точно, но это было бы довольно тривиально, чтобы иметь метод, который перевел от lat/long до координат Холста.

Point ToCanvas(double lat, double lon) {
  double x = ((lon * myCanvas.ActualWidth) / 360.0) - 180.0;
  double y = ((lat * myCanvas.ActualHeight) / 180.0) - 90.0;
  return new Point(x,y);
}

(Или что-то вдоль тех строк)

0
ответ дан 30 November 2019 в 09:38
поделиться

Вот все-XAML решение. Ну, главным образом XAML, потому что у Вас должен быть IValueConverter в коде. Так: Создайте новый проект WPF и добавьте класс к нему. Классом является MultiplyConverter:

namespace YourProject
{
    public class MultiplyConverter : System.Windows.Data.IValueConverter
    {
        public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return AsDouble(value)* AsDouble(parameter);
        }
        double AsDouble(object value)
        {
            var valueText = value as string;
            if (valueText != null)
                return double.Parse(valueText);
            else
                return (double)value;
        }

        public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new System.NotSupportedException();
        }
    }
}

Затем использование этот XAML для Вашего Окна. Теперь необходимо видеть результаты прямо в окне предварительного просмотра XAML.

РЕДАКТИРОВАНИЕ : можно решить Фоновую проблему путем помещения Холста в другом Холсте. Довольно странный, но это работает. Кроме того, я добавил ScaleTransform, который зеркально отражает ось Y так, чтобы положительный Y произошел, и отрицательный снижается. Отметьте тщательно, какие Имена идут где:

<Canvas Name="canvas" Background="Moccasin">
    <Canvas Name="innerCanvas">
        <Canvas.RenderTransform>
            <TransformGroup>
                <TranslateTransform x:Name="translate">
                    <TranslateTransform.X>
                        <Binding ElementName="canvas" Path="ActualWidth"
                                Converter="{StaticResource multiplyConverter}" ConverterParameter="0.5" />
                    </TranslateTransform.X>
                    <TranslateTransform.Y>
                        <Binding ElementName="canvas" Path="ActualHeight"
                                Converter="{StaticResource multiplyConverter}" ConverterParameter="0.5" />
                    </TranslateTransform.Y>
                </TranslateTransform>
                <ScaleTransform ScaleX="1" ScaleY="-1" CenterX="{Binding ElementName=translate,Path=X}"
                        CenterY="{Binding ElementName=translate,Path=Y}" />
            </TransformGroup>
        </Canvas.RenderTransform>
        <Rectangle Canvas.Top="-50" Canvas.Left="-50" Height="100" Width="200" Fill="Blue" />
        <Rectangle Canvas.Top="0" Canvas.Left="0" Height="200" Width="100" Fill="Green" />
        <Rectangle Canvas.Top="-25" Canvas.Left="-25" Height="50" Width="50" Fill="HotPink" />
    </Canvas>
</Canvas>

Что касается Ваших новых требований, чтобы Вам были нужны переменные диапазоны, более сложный ValueConverter, вероятно, добился бы цели.

6
ответ дан 30 November 2019 в 09:38
поделиться

Я предполагаю, что другая опция состояла бы в том, чтобы расширить холст и переопределить меру / располагают заставить его вести себя способ, которым Вы хотите.

0
ответ дан 30 November 2019 в 09:38
поделиться

Можно использовать, преобразовывают для перевода между системами координат, возможно, TransformGroup с TranslateTranform для перемещения (0,0) в центр холста и ScaleTransform для получения координат к правильному диапазону.

С привязкой данных и возможно преобразователем значения или два можно заставить преобразования обновлять автоматически на основе размера холста.

преимущество этого состоит в том, что это будет работать на любой элемент (включая PathGeometry), возможный недостаток - то, что это будет масштабировать все и не только указывает - таким образом, это изменит размер значков и текста на карте.

0
ответ дан 30 November 2019 в 09:38
поделиться

Другое возможное решение:

Вставьте пользовательский холст (draw-to canvas) в другой холст (background canvas) и установите draw-to canvas так, чтобы он был прозрачным и не обрезался по границам. Трансформируйте draw-to canvas с помощью матрицы, которая делает y флипом (M22 = -1) и переводит/масштабирует canvas внутри родительского canvas для просмотра расширения мира, на который вы смотрите.

По сути, если вы рисуете на холсте draw-to canvas при -115, 42, элемент, который вы рисуете, находится "вне" холста, но все равно отображается, потому что холст не обрезается по границам. Затем нужно преобразовать холст draw-to, чтобы точка отобразилась в нужном месте на фоновом холсте.

Это то, что я собираюсь попробовать сам в ближайшее время. Надеюсь, это поможет.

0
ответ дан 30 November 2019 в 09:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: