public override void Dispose(bool isDisposing) { _layer = null; _instances = null; base.Dispose(isDisposing); }
/// <summary> /// Creates a empty GraphDocument with no layers and a standard size of A4 landscape. /// </summary> public GraphDocument() { RootLayer = new HostLayer() { ParentObject = this }; RootLayer.Location = new ItemLocationDirect { SizeX = RADouble.NewAbs(DefaultRootLayerSizeX), SizeY = RADouble.NewAbs(DefaultRootLayerSizeY) }; }
public GraphDocumentPrintTask(HostLayer rootLayer, SingleGraphPrintOptions options) { _layers = rootLayer; _printOptions = options; _page = 0; if (null == _printOptions) { _printOptions = new SingleGraphPrintOptions(); } }
public override bool InitializeDocument(params object[] args) { if (args.Length < 2) { return(false); } if (!(args[1] is HostLayer)) { return(false); } _layer = (HostLayer)args[1]; return(base.InitializeDocument(args)); }
public GraphDocument(GraphDocument from) { using (var suppressToken = SuspendGetToken()) { _creationTime = _lastChangeTime = DateTime.UtcNow; RootLayer = new HostLayer(null, new ItemLocationDirect { SizeX = RADouble.NewAbs(814), SizeY = RADouble.NewAbs(567) }); CopyFrom(from, GraphCopyOptions.All); suppressToken.ResumeSilently(); } }
/// <summary> /// Creates a empty GraphDocument with no layers and a standard size of A4 landscape. /// </summary> public GraphDocument() { _camera = new Camera.OrthographicCamera(); _lighting = new LightSettings(); RootLayer = new HostLayer() { ParentObject = this }; RootLayer.Location = new ItemLocationDirect { SizeX = RADouble.NewAbs(DefaultRootLayerSizeX), SizeY = RADouble.NewAbs(DefaultRootLayerSizeY), SizeZ = RADouble.NewAbs(DefaultRootLayerSizeZ) }; }
protected override IEnumerable <Main.DocumentNodeAndName> GetDocumentNodeChildrenWithName() { if (null != _rootLayer) { yield return(new Main.DocumentNodeAndName(_rootLayer, () => _rootLayer = null, "RootLayer")); } if (null != _graphProperties) { yield return(new Main.DocumentNodeAndName(_graphProperties, () => _graphProperties = null, "GraphProperties")); } if (null != _notes) { yield return(new Main.DocumentNodeAndName(_notes, () => _notes = null, "Notes")); } }
/// <summary> /// Initializes a new instance of the <see cref="EditGridMouseHandler"/> class. /// </summary> /// <param name="view">The view.</param> /// <exception cref="System.ArgumentNullException">view</exception> public EditGridMouseHandler(GraphController view) { if (null == view) { throw new ArgumentNullException("view"); } _grac = view; _grac.SetPanelCursor(Cursors.Arrow); _catchDistance_RLC = 2 / _grac.ZoomFactor; _layerToEdit = _grac.ActiveLayer; while (_layerToEdit != null && _layerToEdit.Layers.Count == 0) { _layerToEdit = _layerToEdit.ParentLayer; // search for a parent layer which has childs } if (_layerToEdit == null) { _layerToEdit = _grac.Doc.RootLayer; } if (_layerToEdit.Grid.XPartitioning.Count == 0 && _layerToEdit.Grid.YPartitioning.Count == 0) { var result = Current.Gui.YesNoMessageBox( string.Format("It seems that layer '{0}' does not define a grid yet.\r\n" + "Do you want to define a grid now based on the position of the existing child layer(s)?", Altaxo.Main.RelativeDocumentPath.GetRelativePathFromTo(_grac.Doc, _layerToEdit).ToString()), "No grid defined!", true); if (result) { _layerToEdit.CreateGridIfNullOrEmpty(); } else { FinishDrawing(); } } UpdateCachedGridLinePositions(); }
/// <summary> /// Shows the layer arrangement dialog and then arranges the layers according to the user input. /// </summary> /// <param name="graph">Graph that contains the layers to arrange.</param> /// <param name="activeLayer">Layer that is currently active.</param> public static void ShowLayerArrangementDialog(this GraphDocument graph, HostLayer activeLayer) { var arrangement = new ArrangeLayersDocument(); object doco = arrangement; if (Current.Gui.ShowDialog(ref doco, "Arrange layers")) { arrangement = (ArrangeLayersDocument)doco; try { ArrangeLayers(activeLayer, arrangement); } catch (Exception ex) { Current.Gui.ErrorMessageBox(ex.Message); } } }
/// <summary> /// Moves the layer specified by index <paramref name="sourcePosition"/> to index <paramref name="destposition"/>. /// </summary> /// <param name="doc">Graph document.</param> /// <param name="parentLayer">The parent layer of the layer to move.</param> /// <param name="sourcePosition">Original index of the layer.</param> /// <param name="destposition">New index of the layer.</param> public static void MoveLayerToPosition(this GraphDocument doc, HostLayer parentLayer, int sourcePosition, int destposition) { if (sourcePosition < 0 && sourcePosition >= parentLayer.Layers.Count) { throw new ApplicationException("sourcePosition is < 0 or sourcePosition >= Layers.Count"); } if (destposition < 0) { throw new ApplicationException("destPosition is < 0"); } var layer = parentLayer.Layers[sourcePosition]; parentLayer.Layers.RemoveAt(sourcePosition); if (destposition > sourcePosition) { destposition--; } parentLayer.Layers.Insert(destposition, layer); }
public XYZPlotLayer(HostLayer parentLayer) : this(parentLayer, GetChildLayerDefaultLocation(), new CS.G3DCartesicCoordinateSystem()) { }
public XYZPlotLayer(HostLayer parentLayer, G3DCoordinateSystem coordinateSystem) : this(parentLayer, GetChildLayerDefaultLocation(), coordinateSystem) { }
/// <summary> /// Creates a layer at the designated <paramref name="location"/> /// </summary> /// <param name="parentLayer">The parent layer of the constructed layer.</param> /// <param name="location">The location of the constructed layer.</param> public XYZPlotLayer(HostLayer parentLayer, IItemLocation location) : this(parentLayer, location, new CS.G3DCartesicCoordinateSystem()) { }
/// <summary> /// Arranges the layers according to the provided options. /// </summary> /// <param name="activeLayer">Layer, whose siblings are about to be arranged. (Exception: If the root layer is the active layer, then the childs of the root layer will be arranged.</param> /// <param name="arrangement">The layer arrangement options (contain the information how to arrange the layers).</param> public static void ArrangeLayers(this HostLayer activeLayer, ArrangeLayersDocument arrangement) { var context = activeLayer.GetPropertyContext(); var parentLayer = activeLayer.ParentLayer ?? activeLayer; int numPresentLayers = parentLayer.Layers.Count; int numDestLayers = arrangement.NumberOfColumns * arrangement.NumberOfRows; int additionalLayers = Math.Max(0, numDestLayers - numPresentLayers); if (null == parentLayer.Grid) { parentLayer.CreateDefaultGrid(); } ArrangeGrid(arrangement, parentLayer.Grid); int nLayer = -1; for (int i = 0; i < arrangement.NumberOfRows; ++i) { for (int j = 0; j < arrangement.NumberOfColumns; ++j) { nLayer++; if (nLayer >= numPresentLayers) { var graph = Altaxo.Graph.Gdi.GraphTemplates.TemplateWithXYPlotLayerWithG2DCartesicCoordinateSystem.CreateGraph(context, Guid.NewGuid().ToString(), "", false); if (graph != null && graph.RootLayer.Layers.Count > 0) { var newLayer = (HostLayer)graph.RootLayer.Layers[0].Clone(); parentLayer.Layers.Add(newLayer); } else { var newLayer = new XYPlotLayer(parentLayer); newLayer.CreateDefaultAxes(context); parentLayer.Layers.Add(newLayer); } } var oldSize = parentLayer.Layers[nLayer].Size; parentLayer.Layers[nLayer].Location = new ItemLocationByGrid { GridColumn = 2 * j + 1, GridRow = 2 * i + 1, GridColumnSpan = 1, GridRowSpan = 1 }; var newSize = parentLayer.Layers[nLayer].Size; } } // act now on superfluous layers if (numPresentLayers > numDestLayers) { switch (arrangement.SuperfluousLayersAction) { case SuperfluousLayersAction.Remove: for (int i = numPresentLayers - 1; i >= numDestLayers; i--) { parentLayer.Layers.RemoveAt(i); } break; case SuperfluousLayersAction.OverlayFirstLayer: case SuperfluousLayersAction.OverlayLastLayer: int template = arrangement.SuperfluousLayersAction == SuperfluousLayersAction.OverlayFirstLayer ? 0 : numDestLayers - 1; var templateLayer = parentLayer.Layers[template]; for (int i = numDestLayers; i < numPresentLayers; i++) { var oldSize = parentLayer.Layers[i].Size; parentLayer.Layers[i].Location = (IItemLocation)templateLayer.Location.Clone(); var newSize = parentLayer.Layers[i].Size; } break; } } }
public GraphDocumentPrintTask(HostLayer rootLayer, SingleGraphPrintOptions options) { _layers = rootLayer; _printOptions = options; _page = 0; if (null == _printOptions) _printOptions = new SingleGraphPrintOptions(); }
/// <summary> /// Gets the hit point on that plane of the active layer rectangle, that is facing the camera. /// </summary> /// <param name="doc">The graph document containing the active layer.</param> /// <param name="activeLayer">The active layer of the graph document.</param> /// <param name="hitposition">Hit point in relative screen coordinates. The z-component is the aspect ratio of the screen (y/x).</param> /// <param name="hitPointOnPlaneInActiveLayerCoordinates">Output: The hit point on the plane of the active layer that faces the camera. The hit point is returned in active layer coordinates.</param> /// <param name="rotationsRadian">The rotation angles that can be used e.g. to orient text so that the text is most readable from the current camera setting. Rotation angle around x is the x-component of the returned vector, and so on.</param> /// <exception cref="InvalidProgramException">There should always be a plane of a rectangle that can be hit!</exception> public static void GetHitPointOnActiveLayerPlaneFacingTheCamera(GraphDocument doc, HostLayer activeLayer, PointD3D hitposition, out PointD3D hitPointOnPlaneInActiveLayerCoordinates, out VectorD3D rotationsRadian) { var activeLayerTransformation = activeLayer.TransformationFromRootToHere(); var camera = doc.Camera; var hitData = new HitTestPointData(camera.GetHitRayMatrix(hitposition)); hitData = hitData.NewFromAdditionalTransformation(activeLayerTransformation); // now hitdata are in layer cos var targetToEye = hitData.WorldTransformation.Transform(camera.TargetToEyeVectorNormalized); // targetToEye in layer coordinates var upEye = hitData.WorldTransformation.Transform(camera.UpVectorPerpendicularToEyeVectorNormalized); // camera up vector in layer coordinates // get the face which has the best dot product between the eye vector of the camera and the plane's normal var layerRect = new RectangleD3D(PointD3D.Empty, activeLayer.Size); double maxval = double.MinValue; PlaneD3D maxPlane = PlaneD3D.Empty; foreach (var plane in layerRect.Planes) { double val = VectorD3D.DotProduct(plane.Normal, targetToEye); if (val > maxval) { maxval = val; maxPlane = plane; } } bool isHit = hitData.IsPlaneHitByRay(maxPlane, out hitPointOnPlaneInActiveLayerCoordinates); // hitPointOnPlane is in layer coordinates too if (!isHit) throw new InvalidProgramException("There should always be a plane of a rectangle that can be hit!"); VectorD3D zaxis = maxPlane.Normal; VectorD3D yaxis = upEye; // Find y axis perpendicular to zaxis maxval = double.MinValue; foreach (var plane in layerRect.Planes) { double val = VectorD3D.DotProduct(plane.Normal, upEye); if (val > maxval && 0 == VectorD3D.DotProduct(plane.Normal, zaxis)) { maxval = val; yaxis = plane.Normal; } } var xaxis = VectorD3D.CrossProduct(yaxis, zaxis); // now we have all information about the spatial position and orientation of the text: // hitPointOnPlane is the position of the text // maxPlane.Normal is the face orientation of the text // maxUpVector is the up orientation of the text double cx, sx, cy, sy, cz, sz; sy = xaxis.Z; if (1 != Math.Abs(sy)) { cy = Math.Sqrt(1 - sy * sy); cz = xaxis.X / cy; sz = xaxis.Y / cy; sx = yaxis.Z / cy; cx = zaxis.Z / cy; } else // sy is +1, thus cy is zero { // we set x-rotation to zero, i.e. cx==1 and sx==0 cy = 0; cx = 1; sx = 0; cz = yaxis.Y; sz = -yaxis.X; } rotationsRadian = new VectorD3D(Math.Atan2(sx, cx), Math.Atan2(sy, cy), Math.Atan2(sz, cz)); }
protected override void InternalCopyGraphItems(HostLayer from, Gdi.GraphCopyOptions options) { bool bGraphItems = options.HasFlag(Gdi.GraphCopyOptions.CopyLayerGraphItems); bool bChildLayers = options.HasFlag(Gdi.GraphCopyOptions.CopyChildLayers); bool bLegends = options.HasFlag(Gdi.GraphCopyOptions.CopyLayerLegends); var criterium = new Func<IGraphicBase, bool>(x => { if (x is Gdi.HostLayer) return bChildLayers; if (x is LegendText) return bLegends; return bGraphItems; }); InternalCopyGraphItems(from, options, criterium); }
/// <summary> /// Gets the hit point on that plane of the active layer rectangle, that is facing the camera. /// </summary> /// <param name="doc">The graph document containing the active layer.</param> /// <param name="activeLayer">The active layer of the graph document.</param> /// <param name="hitposition">Hit point in relative screen coordinates. The z-component is the aspect ratio of the screen (y/x).</param> /// <param name="hitPointOnPlaneInActiveLayerCoordinates">Output: The hit point on the plane of the active layer that faces the camera. The hit point is returned in active layer coordinates.</param> /// <param name="rotationsRadian">The rotation angles that can be used e.g. to orient text so that the text is most readable from the current camera setting. Rotation angle around x is the x-component of the returned vector, and so on.</param> /// <exception cref="InvalidProgramException">There should always be a plane of a rectangle that can be hit!</exception> public static void GetHitPointOnActiveLayerPlaneFacingTheCamera(GraphDocument doc, HostLayer activeLayer, PointD3D hitposition, out PointD3D hitPointOnPlaneInActiveLayerCoordinates, out VectorD3D rotationsRadian) { var activeLayerTransformation = activeLayer.TransformationFromRootToHere(); var camera = doc.Camera; var hitData = new HitTestPointData(camera.GetHitRayMatrix(hitposition)); hitData = hitData.NewFromAdditionalTransformation(activeLayerTransformation); // now hitdata are in layer cos var targetToEye = hitData.WorldTransformation.Transform(camera.TargetToEyeVectorNormalized); // targetToEye in layer coordinates var upEye = hitData.WorldTransformation.Transform(camera.UpVectorPerpendicularToEyeVectorNormalized); // camera up vector in layer coordinates // get the face which has the best dot product between the eye vector of the camera and the plane's normal var layerRect = new RectangleD3D(PointD3D.Empty, activeLayer.Size); double maxval = double.MinValue; PlaneD3D maxPlane = PlaneD3D.Empty; foreach (var plane in layerRect.Planes) { double val = VectorD3D.DotProduct(plane.Normal, targetToEye); if (val > maxval) { maxval = val; maxPlane = plane; } } bool isHit = hitData.IsPlaneHitByRay(maxPlane, out hitPointOnPlaneInActiveLayerCoordinates); // hitPointOnPlane is in layer coordinates too if (!isHit) { throw new InvalidProgramException("There should always be a plane of a rectangle that can be hit!"); } VectorD3D zaxis = maxPlane.Normal; VectorD3D yaxis = upEye; // Find y axis perpendicular to zaxis maxval = double.MinValue; foreach (var plane in layerRect.Planes) { double val = VectorD3D.DotProduct(plane.Normal, upEye); if (val > maxval && 0 == VectorD3D.DotProduct(plane.Normal, zaxis)) { maxval = val; yaxis = plane.Normal; } } var xaxis = VectorD3D.CrossProduct(yaxis, zaxis); // now we have all information about the spatial position and orientation of the text: // hitPointOnPlane is the position of the text // maxPlane.Normal is the face orientation of the text // maxUpVector is the up orientation of the text double cx, sx, cy, sy, cz, sz; sy = xaxis.Z; if (1 != Math.Abs(sy)) { cy = Math.Sqrt(1 - sy * sy); cz = xaxis.X / cy; sz = xaxis.Y / cy; sx = yaxis.Z / cy; cx = zaxis.Z / cy; } else // sy is +1, thus cy is zero { // we set x-rotation to zero, i.e. cx==1 and sx==0 cy = 0; cx = 1; sx = 0; cz = yaxis.Y; sz = -yaxis.X; } rotationsRadian = new VectorD3D(Math.Atan2(sx, cx), Math.Atan2(sy, cy), Math.Atan2(sz, cz)); }
/// <summary> /// Creates a layer at the provided <paramref name="location"/>. /// </summary> /// <param name="parentLayer">The parent layer of the newly created layer.</param> /// <param name="location">The position of the layer on the printable area in points (1/72 inch).</param> /// <param name="coordinateSystem">The coordinate system to use for the layer.</param> public XYZPlotLayer(HostLayer parentLayer, IItemLocation location, G3DCoordinateSystem coordinateSystem) : base(parentLayer, location) { this.CoordinateSystem = coordinateSystem; this.AxisStyles = new AxisStyleCollection(); this.Scales = new ScaleCollection(3); this.GridPlanes = new GridPlaneCollection(); this.GridPlanes.Add(new GridPlane(CSPlaneID.Front)); this.PlotItems = new PlotItemCollection(this); }
/// <summary> /// Gets the principal coordinate system that results of the camera facing a layer. The plane of the layer that best faced the camera is used for the calculations. /// The normal of that layer is returned as z-axis, the vector that best matches the up-vector of the camera is becoming the y-axis, /// and the x-axis results from the z-axis and the y-axis. /// </summary> /// <param name="camera">The camera.</param> /// <param name="activeLayer">The active layer of the graph document.</param> /// <param name="transformation">Matrix that contains the principal axes as described above. The axes coordinates are in the coordinates of the layer provided in the argument <paramref name="activeLayer"/>.</param> /// <exception cref="InvalidProgramException">There should always be a plane of a rectangle that can be hit!</exception> public static void GetCoordinateSystemBasedOnLayerPlaneFacingTheCamera(CameraBase camera, HostLayer activeLayer, out Matrix3x3 transformation) { PointD3D hitposition = new PointD3D(0.5, 0.5, 1); // this hit position is arbitrary, every other position should work similarly var activeLayerTransformation = activeLayer.TransformationFromRootToHere(); var hitData = new HitTestPointData(camera.GetHitRayMatrix(hitposition)); hitData = hitData.NewFromAdditionalTransformation(activeLayerTransformation); // now hitdata are in layer cos var targetToEye = hitData.WorldTransformation.Transform(camera.TargetToEyeVectorNormalized); // targetToEye in layer coordinates var upEye = hitData.WorldTransformation.Transform(camera.UpVectorPerpendicularToEyeVectorNormalized); // camera up vector in layer coordinates // get the face which has the best dot product between the eye vector of the camera and the plane's normal var layerRect = new RectangleD3D(PointD3D.Empty, activeLayer.Size); double maxval = double.MinValue; PlaneD3D maxPlane = PlaneD3D.Empty; foreach (var plane in layerRect.Planes) { double val = VectorD3D.DotProduct(plane.Normal, targetToEye); if (val > maxval) { maxval = val; maxPlane = plane; } } // bool isHit = hitData.IsPlaneHitByRay(maxPlane, out hitPointOnPlaneInActiveLayerCoordinates); // hitPointOnPlane is in layer coordinates too // if (!isHit) // throw new InvalidProgramException("There should always be a plane of a rectangle that can be hit!"); VectorD3D zaxis = maxPlane.Normal; VectorD3D yaxis = upEye; // Find y axis perpendicular to zaxis maxval = double.MinValue; foreach (var plane in layerRect.Planes) { double val = VectorD3D.DotProduct(plane.Normal, upEye); if (val > maxval && 0 == VectorD3D.DotProduct(plane.Normal, zaxis)) { maxval = val; yaxis = plane.Normal; } } var xaxis = VectorD3D.CrossProduct(yaxis, zaxis); // now we have all information about the spatial position and orientation of the text: // hitPointOnPlane is the position of the text // maxPlane.Normal is the face orientation of the text // maxUpVector is the up orientation of the text xaxis = xaxis.Normalized; yaxis = yaxis.Normalized; zaxis = zaxis.Normalized; transformation = new Matrix3x3( xaxis.X, yaxis.X, zaxis.X, xaxis.Y, yaxis.Y, zaxis.Y, xaxis.Z, yaxis.Z, zaxis.Z ); }
/// <summary> /// Shows the layer arrangement dialog and then arranges the layers according to the user input. /// </summary> /// <param name="graph">Graph that contains the layers to arrange.</param> /// <param name="activeLayer">Layer that is currently active.</param> public static void ShowLayerArrangementDialog(this GraphDocument graph, HostLayer activeLayer) { ArrangeLayersDocument arrangement = new ArrangeLayersDocument(); object doco = arrangement; if (Current.Gui.ShowDialog(ref doco, "Arrange layers")) { arrangement = (ArrangeLayersDocument)doco; try { ArrangeLayers(activeLayer, arrangement); } catch (Exception ex) { Current.Gui.ErrorMessageBox(ex.Message); } } }
/// <summary> /// Moves the layer specified by index <paramref name="sourcePosition"/> to index <paramref name="destposition"/>. /// </summary> /// <param name="doc">Graph document.</param> /// <param name="parentLayer">The parent layer of the layer to move.</param> /// <param name="sourcePosition">Original index of the layer.</param> /// <param name="destposition">New index of the layer.</param> public static void MoveLayerToPosition(this GraphDocument doc, HostLayer parentLayer, int sourcePosition, int destposition) { if (sourcePosition < 0 && sourcePosition >= parentLayer.Layers.Count) throw new ApplicationException("sourcePosition is < 0 or sourcePosition >= Layers.Count"); if (destposition < 0) throw new ApplicationException("destPosition is < 0"); var layer = parentLayer.Layers[sourcePosition]; parentLayer.Layers.RemoveAt(sourcePosition); if (destposition > sourcePosition) destposition--; parentLayer.Layers.Insert(destposition, layer); }
/// <summary> /// Internal copy from operation. It is presumed, that the events are already suspended. Additionally, /// it is not neccessary to call the OnChanged event, since this is called in the calling routine. /// </summary> /// <param name="obj">The object (layer) from which to copy.</param> /// <param name="options">Copy options.</param> protected override void InternalCopyFrom(HostLayer obj, Gdi.GraphCopyOptions options) { base.InternalCopyFrom(obj, options); // base copy, but keep in mind that InternalCopyGraphItems is overridden in this class var from = obj as XYZPlotLayer; if (null == from) return; if (0 != (options & Gdi.GraphCopyOptions.CopyLayerScales)) { this.CoordinateSystem = from.CoordinateSystem; // immutable this.Scales = (ScaleCollection)from._scales.Clone(); this._dataClipping = from._dataClipping; } if (0 != (options & Gdi.GraphCopyOptions.CopyLayerGrid)) { this.GridPlanes = from._gridPlanes.Clone(); } // Styles if (0 != (options & Gdi.GraphCopyOptions.CopyLayerAxes)) { this.AxisStyles = (AxisStyleCollection)from._axisStyles.Clone(); } // Plot items if (0 != (options & Gdi.GraphCopyOptions.CopyLayerPlotItems)) { this.PlotItems = null == from._plotItems ? null : new PlotItemCollection(this, from._plotItems, true); } else if (0 != (options & Gdi.GraphCopyOptions.CopyLayerPlotStyles)) { // TODO apply the styles from from._plotItems to the PlotItems here this.PlotItems.CopyFrom(from._plotItems, options); } }