public static Vector Add(Vector vector1, Vector vector2) { return new Vector(vector1.x + vector2.x, vector1.y + vector2.y); }
public static double CrossProduct(Vector vector1, Vector vector2) { return ((vector1.x*vector2.y) - (vector1.y*vector2.x)); }
public static double AngleBetween(Vector vector1, Vector vector2) { double y = (vector1.x*vector2.y) - (vector2.x*vector1.y); double x = (vector1.x*vector2.x) + (vector1.y*vector2.y); return (Math.Atan2(y, x)*57.295779513082323); }
public static bool Equals(Vector vector1, Vector vector2) { return (vector1.X.Equals(vector2.X) && vector1.Y.Equals(vector2.Y)); }
public bool Equals(Vector value) { return Equals(this, value); }
public static double Multiply(Vector vector1, Vector vector2) { return ((vector1.x*vector2.x) + (vector1.y*vector2.y)); }
public static double Determinant(Vector vector1, Vector vector2) { return ((vector1.x*vector2.y) - (vector1.y*vector2.x)); }
public static Point Add(Vector vector, Point point) { return new Point(point.x + vector.x, point.y + vector.y); }
public static Vector Multiply(int scalar, Vector vector) { return new Vector(vector.x*scalar, vector.y*scalar); }
/// <summary> /// Накладывает буфер дочернего элемента на текущий. Дочерний буфер виртуально накладывается на текущий /// в соответствии с переданным actualOffset, а потом та часть дочернего буфера, которая попадает в /// renderSlotRect, прорисовывается. renderSlotRect определен отн-но текущего буфера (а не дочернего). /// layoutClip определяет, какая часть дочернего буфера будет прорисована в текущий буфер (клиппинг, /// возникающий при применении Margin и Alignment'ов). /// </summary> /// <param name="childBuffer"></param> /// <param name="actualOffset">Смещение буфера дочернего элемента относительно текущего.</param> /// <param name="childRenderSize">Размер отрендеренного дочерним элементом контента - может /// быть меньше размера childBuffer, поэтому нужно передавать явно.</param> /// <param name="renderSlotRect">Размер и положение слота, выделенного дочернему элементу.</param> /// <param name="layoutClip">Часть дочернего буфера, которая будет отрисована - по размеру может быть /// меньше или равна RenderSlotRect.Size. По координатам соотносится с childBuffer.</param> public void ApplyChild(RenderingBuffer childBuffer, Vector actualOffset, Size childRenderSize, Rect renderSlotRect, Rect layoutClip) { ApplyChild( childBuffer, actualOffset, childRenderSize, renderSlotRect, layoutClip, null ); }
public static Vector Subtract(Vector vector1, Vector vector2) { return new Vector(vector1.x - vector2.x, vector1.y - vector2.y); }
/// <summary> /// Оверлоад для оптимизированного наложения в случае, когда известно, что в дочернем /// контроле поменялась лишь часть, идентифицируемая параметром affectedRect. /// Будет обработана только эта часть дочернего контрола, и количество операций уменьшится. /// </summary> /// <param name="childBuffer"></param> /// <param name="actualOffset"></param> /// <param name="childRenderSize"></param> /// <param name="renderSlotRect"></param> /// <param name="layoutClip"></param> /// <param name="affectedRect">Прямоугольник в дочернем контроле, который был изменен.</param> public void ApplyChild(RenderingBuffer childBuffer, Vector actualOffset, Size childRenderSize, Rect renderSlotRect, Rect layoutClip, Rect? affectedRect) { // Считаем finalRect - прямоугольник относительно parent, который нужно закрасить Rect finalRect = layoutClip; if (affectedRect != null) finalRect.Intersect(affectedRect.Value); // Если child.RenderSlotRect больше child.RenderSize, а rendering buffer // дочернего контрола больше его RenderSize (такое бывает после уменьшения // размеров контрола - т.к. буфер может только увеличиваться, но не уменьшаться) - // то нам нужно либо передать в метод ApplyChild и child.RenderSize, либо // выполнить пересечение заранее finalRect.Intersect(new Rect(new Point(0, 0), childRenderSize)); // Because cannot call Offset() method of empty rect if ( finalRect.IsEmpty ) return; finalRect.Offset(actualOffset); finalRect.Intersect( renderSlotRect ); // Нужно также учесть размеры буфера текущего контрола finalRect.Intersect( new Rect(new Point(0, 0), new Size(this.width, this.height)) ); for ( int x = finalRect.Left; x < finalRect.Right; x++ ) { int parentX = x; int childX = parentX - actualOffset.x; for ( int y = finalRect.Top; y < finalRect.Bottom; y++ ) { int parentY = y; int childY = parentY - actualOffset.y; CHAR_INFO charInfo = childBuffer.buffer[childX, childY]; int opacity = childBuffer.opacityMatrix[childX, childY]; // Для полностью прозрачных пикселей родительского буфера - присваиваем и значение // пикселя, и значение opacity, дальше дело за следующим родителем if ( this.opacityMatrix[ parentX, parentY ] == 2 || this.opacityMatrix[ parentX, parentY ] == 6 ) { this.buffer[ parentX, parentY ] = charInfo; this.opacityMatrix[ parentX, parentY ] = opacity; } else { // В остальных случаях opacity родительского буфера остаётся, а // сам пиксель зависит от opacity дочернего элемента if ( opacity == 0 || opacity == 4 ) { this.buffer[ parentX, parentY ] = charInfo; } else if ( opacity == 1 || opacity == 5 ) { charInfo.Attributes = Colors.Blend( Color.DarkGray, Color.Black ); charInfo.UnicodeChar = buffer[ parentX, parentY ].UnicodeChar; buffer[ parentX, parentY ] = charInfo; } else if ( opacity == 3 || opacity == 7 ) { // берем фоновые атрибуты символа из родительского буфера Attr parentAttr = buffer[ parentX, parentY ].Attributes; if ( ( parentAttr & Attr.BACKGROUND_BLUE ) == Attr.BACKGROUND_BLUE ) { charInfo.Attributes |= Attr.BACKGROUND_BLUE; } else { charInfo.Attributes &= ~Attr.BACKGROUND_BLUE; } if ( ( parentAttr & Attr.BACKGROUND_GREEN ) == Attr.BACKGROUND_GREEN ) { charInfo.Attributes |= Attr.BACKGROUND_GREEN; } else { charInfo.Attributes &= ~Attr.BACKGROUND_GREEN; } if ( ( parentAttr & Attr.BACKGROUND_RED ) == Attr.BACKGROUND_RED ) { charInfo.Attributes |= Attr.BACKGROUND_RED; } else { charInfo.Attributes &= ~Attr.BACKGROUND_RED; } if ( ( parentAttr & Attr.BACKGROUND_INTENSITY ) == Attr.BACKGROUND_INTENSITY ) { charInfo.Attributes |= Attr.BACKGROUND_INTENSITY; } else { charInfo.Attributes &= ~Attr.BACKGROUND_INTENSITY; } buffer[ parentX, parentY ] = charInfo; } } } } }
public static Rect Offset(Rect rect, Vector offsetVector) { rect.Offset(offsetVector.X, offsetVector.Y); return rect; }
public void Offset(Vector offsetVector) { if (this.IsEmpty) { throw new InvalidOperationException("Rect_CannotCallMethod"); } this.x += offsetVector.x; this.y += offsetVector.y; }
public Rect(Point point, Vector vector) : this(point, point + vector) { }
public void Window_OnMouseMove(object sender, MouseEventArgs args) { if (closing) { Point point = args.GetPosition(this); bool anyChanged = false; if (point.x == 3 && point.y == 0) { if (!showClosingGlyph) { showClosingGlyph = true; anyChanged = true; } } else { if (showClosingGlyph) { showClosingGlyph = false; anyChanged = true; } } if (anyChanged) Invalidate(); args.Handled = true; } if (moving) { Point parentPoint = args.GetPosition(getWindowsHost()); Vector vector = new Vector(parentPoint.X - movingStartPoint.x, parentPoint.Y - movingStartPoint.y); X = movingStartX + vector.X; Y = movingStartY + vector.Y; getWindowsHost().Invalidate(); args.Handled = true; } if (resizing) { Point parentPoint = args.GetPosition(getWindowsHost()); int deltaWidth = parentPoint.X - resizingStartPoint.x; int deltaHeight = parentPoint.Y - resizingStartPoint.y; int width = resizingStartWidth + deltaWidth; int height = resizingStartHeight + deltaHeight; bool anyChanged = false; if (width >= 4) { this.Width = width; anyChanged = true; } if (height >= 3) { this.Height = height; anyChanged = true; } if (anyChanged) Invalidate(); args.Handled = true; } }