1 | ///
|
---|
2 | /// This file is part of ILNumerics Community Edition.
|
---|
3 | ///
|
---|
4 | /// ILNumerics Community Edition - high performance computing for applications.
|
---|
5 | /// Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
|
---|
6 | ///
|
---|
7 | /// ILNumerics Community Edition is free software: you can redistribute it and/or modify
|
---|
8 | /// it under the terms of the GNU General Public License version 3 as published by
|
---|
9 | /// the Free Software Foundation.
|
---|
10 | ///
|
---|
11 | /// ILNumerics Community Edition is distributed in the hope that it will be useful,
|
---|
12 | /// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | /// GNU General Public License for more details.
|
---|
15 | ///
|
---|
16 | /// You should have received a copy of the GNU General Public License
|
---|
17 | /// along with ILNumerics Community Edition. See the file License.txt in the root
|
---|
18 | /// of your distribution package. If not, see <http://www.gnu.org/licenses/>.
|
---|
19 | ///
|
---|
20 | /// In addition this software uses the following components and/or licenses:
|
---|
21 | ///
|
---|
22 | /// =================================================================================
|
---|
23 | /// The Open Toolkit Library License
|
---|
24 | ///
|
---|
25 | /// Copyright (c) 2006 - 2009 the Open Toolkit library.
|
---|
26 | ///
|
---|
27 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
|
---|
28 | /// of this software and associated documentation files (the "Software"), to deal
|
---|
29 | /// in the Software without restriction, including without limitation the rights to
|
---|
30 | /// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
---|
31 | /// the Software, and to permit persons to whom the Software is furnished to do
|
---|
32 | /// so, subject to the following conditions:
|
---|
33 | ///
|
---|
34 | /// The above copyright notice and this permission notice shall be included in all
|
---|
35 | /// copies or substantial portions of the Software.
|
---|
36 | ///
|
---|
37 | /// =================================================================================
|
---|
38 | ///
|
---|
39 |
|
---|
40 | #pragma warning disable 1591
|
---|
41 |
|
---|
42 | using System;
|
---|
43 | using System.Collections.Generic;
|
---|
44 | using System.Text;
|
---|
45 | using System.Drawing;
|
---|
46 | using System.Reflection;
|
---|
47 | using System.Windows.Forms;
|
---|
48 | using System.IO;
|
---|
49 | using ILNumerics.Drawing;
|
---|
50 | using ILNumerics.Drawing.Interfaces;
|
---|
51 | using ILNumerics.Drawing.Collections;
|
---|
52 | using ILNumerics.Drawing.Graphs;
|
---|
53 | using ILNumerics.Drawing.Labeling;
|
---|
54 | using ILNumerics.Drawing.Misc;
|
---|
55 | using System.Diagnostics;
|
---|
56 |
|
---|
57 | namespace ILNumerics.Drawing {
|
---|
58 |
|
---|
59 | /// <summary>
|
---|
60 | /// Basic abstract base class for GL dependent display.
|
---|
61 | /// </summary>
|
---|
62 | /// <remarks>This control is the main plot control of ILNumerics.</remarks>
|
---|
63 | public abstract class ILPanel : Control {
|
---|
64 |
|
---|
65 | #region attributes
|
---|
66 | protected ILRendererManager m_textRendererManager;
|
---|
67 | protected ILClippingData m_clippingView;
|
---|
68 | protected ILAxisCollection m_axes;
|
---|
69 | protected ILGraphCollection m_graphs;
|
---|
70 | protected ILTextureManager m_textureManager;
|
---|
71 | protected Point m_mouseStart;
|
---|
72 | protected bool m_isDragging;
|
---|
73 | protected bool m_active = false;
|
---|
74 | protected bool m_drawHidden = true;
|
---|
75 | protected bool m_ready = false;
|
---|
76 | private bool m_isStartingUp = true;
|
---|
77 | protected ILCamera m_camera;
|
---|
78 | protected ILCamera m_defaultView;
|
---|
79 | protected bool m_autoDefaultView = true;
|
---|
80 | protected InteractiveModes m_selectingMode = InteractiveModes.Rotating;
|
---|
81 | protected InteractiveModes m_oldSelectingMode;
|
---|
82 | protected bool m_isCtrlKeyDown;
|
---|
83 | protected ILPoint3Df m_scaling;
|
---|
84 | protected Projection m_projection = Projection.Orthographic;
|
---|
85 | protected Color m_backColor = Color.FromKnownColor(KnownColor.Control);
|
---|
86 | protected Color m_cubeBGColor = Color.FromArgb(250, 250, 250);
|
---|
87 | protected ILColormap m_colormap;
|
---|
88 | protected ILLegend m_legend;
|
---|
89 | protected ZoomModes m_zoomMode = ZoomModes.RollHard;
|
---|
90 | protected ILZoomAction m_zoomAction;
|
---|
91 | protected float m_zoomOffset = 50f;
|
---|
92 | protected GraphicDeviceType m_graphicsDevice;
|
---|
93 | protected ILLineProperties m_selectionRectangle;
|
---|
94 | protected bool m_fillBackground = true;
|
---|
95 | private AutoZoomOptions m_autoZoomOptions = AutoZoomOptions.OnDataChanges;
|
---|
96 | protected ILLayoutData m_layoutData = new ILLayoutData();
|
---|
97 | protected ILLightCollection m_lights = new ILLightCollection();
|
---|
98 | protected ILRenderProperties m_renderProperties;
|
---|
99 | protected ILAction m_action;
|
---|
100 | protected List<ILGraph> m_sortingCacheList = new List<ILGraph>();
|
---|
101 | /// <summary>
|
---|
102 | /// pixel size of the current PlotCubeScreenRectangle
|
---|
103 | /// </summary>
|
---|
104 | protected RectangleF m_plotBoxScreenRectF;
|
---|
105 | protected PlotBoxScreenSizeMode m_plotBoxScreenSizeMode;
|
---|
106 | protected AspectRatioMode m_aspectRatio;
|
---|
107 | protected double[] m_clipplanes = new double[24];
|
---|
108 |
|
---|
109 | private const int MAXRENDERPASSES = 2;
|
---|
110 | private const float LABELS_VERTICAL_MIN_RHO = 0.8f;
|
---|
111 | protected const float pi05 = (float) Math.PI / 2;
|
---|
112 | protected const float pi2 = (float) Math.PI * 2;
|
---|
113 | protected const float pi32 = (float) Math.PI / 2 * 3;
|
---|
114 | protected const float pi4 = (float) Math.PI / 4;
|
---|
115 | protected const float pi8 = (float) Math.PI / 8;
|
---|
116 | #endregion
|
---|
117 |
|
---|
118 | #region properties
|
---|
119 | /// <summary>
|
---|
120 | /// Gets the mode for automatic view angle updates or sets it
|
---|
121 | /// </summary>
|
---|
122 | public bool AutoDefaultView {
|
---|
123 | get { return m_autoDefaultView; }
|
---|
124 | set { m_autoDefaultView = value; }
|
---|
125 | }
|
---|
126 | /// <summary>
|
---|
127 | /// Determines how the projected data plots are mapped to PlotCubeScreenRectF
|
---|
128 | /// </summary>
|
---|
129 | public AspectRatioMode AspectRatio {
|
---|
130 | get { return m_aspectRatio; }
|
---|
131 | set { m_aspectRatio = value; }
|
---|
132 | }
|
---|
133 | /// <summary>
|
---|
134 | /// The normalizes projected size (range 0..1) of plot cube on 2D client area, on set: also sets PlotCubeScreenMode -> Manual
|
---|
135 | /// </summary>
|
---|
136 | public RectangleF PlotBoxScreenRect {
|
---|
137 | get { return m_plotBoxScreenRectF; }
|
---|
138 | set {
|
---|
139 | m_plotBoxScreenRectF = value;
|
---|
140 | m_plotBoxScreenSizeMode = PlotBoxScreenSizeMode.Manual;
|
---|
141 | //Invalidate();
|
---|
142 | }
|
---|
143 | }
|
---|
144 | /// <summary>
|
---|
145 | /// Options for determining the size of the plot cube on the 2D screen client area, default: optimal
|
---|
146 | /// </summary>
|
---|
147 | public PlotBoxScreenSizeMode PlotBoxScreenSizeMode {
|
---|
148 | get { return m_plotBoxScreenSizeMode; }
|
---|
149 | set {
|
---|
150 | m_plotBoxScreenSizeMode = value;
|
---|
151 | if (value == PlotBoxScreenSizeMode.Maximum) {
|
---|
152 | m_plotBoxScreenRectF = new RectangleF(0, 0, 1f, 1f);
|
---|
153 | }
|
---|
154 | }
|
---|
155 | }
|
---|
156 | /// <summary>
|
---|
157 | /// Access collection of lights for configuration
|
---|
158 | /// </summary>
|
---|
159 | public ILLightCollection Lights {
|
---|
160 | get { return m_lights; }
|
---|
161 | }
|
---|
162 | /// <summary>
|
---|
163 | /// Legend for panel's graphs
|
---|
164 | /// </summary>
|
---|
165 | public ILLegend Legend {
|
---|
166 | get {
|
---|
167 | return m_legend;
|
---|
168 | }
|
---|
169 | }
|
---|
170 | /// <summary>
|
---|
171 | /// Get texture manager instance, storing all textures used in the scene
|
---|
172 | /// </summary>
|
---|
173 | internal ILTextureManager TextureManager {
|
---|
174 | get {
|
---|
175 | return m_textureManager;
|
---|
176 | }
|
---|
177 | }
|
---|
178 | /// <summary>
|
---|
179 | /// Colormap used to translate color indices into true colors
|
---|
180 | /// </summary>
|
---|
181 | public ILColormap Colormap {
|
---|
182 | get {
|
---|
183 | return m_colormap;
|
---|
184 | }
|
---|
185 | set {
|
---|
186 | m_colormap = value;
|
---|
187 | OnColormapChanged();
|
---|
188 | }
|
---|
189 | }
|
---|
190 | /// <summary>
|
---|
191 | /// Determines if background of the rendering cube will be filled with the CubeBackgroundColor property value
|
---|
192 | /// </summary>
|
---|
193 | public bool BackgroundFilled {
|
---|
194 | get {
|
---|
195 | return m_fillBackground;
|
---|
196 | }
|
---|
197 | set {
|
---|
198 | m_fillBackground = value;
|
---|
199 | //Invalidate();
|
---|
200 | }
|
---|
201 | }
|
---|
202 | /// <summary>
|
---|
203 | /// True: the control will always be drawn, even if it does not own the focus
|
---|
204 | /// </summary>
|
---|
205 | public bool DrawInactive {
|
---|
206 | get {
|
---|
207 | return m_drawHidden;
|
---|
208 | }
|
---|
209 | set {
|
---|
210 | m_drawHidden = value;
|
---|
211 | //Invalidate();
|
---|
212 | }
|
---|
213 | }
|
---|
214 | /// <summary>
|
---|
215 | /// Get/set the background color for the inner cube drawing
|
---|
216 | /// </summary>
|
---|
217 | public Color BackColorCube {
|
---|
218 | get {
|
---|
219 | return m_cubeBGColor;
|
---|
220 | }
|
---|
221 | set {
|
---|
222 | m_cubeBGColor = value;
|
---|
223 | //Invalidate();
|
---|
224 | }
|
---|
225 | }
|
---|
226 | /// <summary>
|
---|
227 | /// View settings, get access to the clipping limits for all axises
|
---|
228 | /// </summary>
|
---|
229 | public ILClippingData Limits {
|
---|
230 | get {
|
---|
231 | return m_clippingView;
|
---|
232 | }
|
---|
233 | }
|
---|
234 | /// <summary>
|
---|
235 | /// Get the type of device currently used for rendering
|
---|
236 | /// </summary>
|
---|
237 | public GraphicDeviceType GraphicDeviceType {
|
---|
238 | get {
|
---|
239 | return m_graphicsDevice;
|
---|
240 | }
|
---|
241 | }
|
---|
242 | /// <summary>
|
---|
243 | /// Get/set properties for selection rectangle, drawn when zooming with the mouse
|
---|
244 | /// </summary>
|
---|
245 | public ILLineProperties SelectionRectangle {
|
---|
246 | get {
|
---|
247 | return m_selectionRectangle;
|
---|
248 | }
|
---|
249 | }
|
---|
250 | /// <summary>
|
---|
251 | /// color of the figure background
|
---|
252 | /// </summary>
|
---|
253 | public override Color BackColor {
|
---|
254 | get {
|
---|
255 | return m_backColor;
|
---|
256 | }
|
---|
257 | set {
|
---|
258 | m_backColor = value;
|
---|
259 | //Invalidate();
|
---|
260 | }
|
---|
261 | }
|
---|
262 | /// <summary>
|
---|
263 | /// type of projection: orthographic (default) or perspective
|
---|
264 | /// </summary>
|
---|
265 | public Projection Projection {
|
---|
266 | get {
|
---|
267 | return m_projection;
|
---|
268 | }
|
---|
269 | set {
|
---|
270 | m_projection = value;
|
---|
271 | //Invalidate();
|
---|
272 | }
|
---|
273 | }
|
---|
274 | /// <summary>
|
---|
275 | /// Get or set viewport properties (distance & angles)
|
---|
276 | /// </summary>
|
---|
277 | /// <remarks>Changing </remarks>
|
---|
278 | public ILCamera Camera {
|
---|
279 | get {
|
---|
280 | return m_camera;
|
---|
281 | }
|
---|
282 | }
|
---|
283 | /// <summary>
|
---|
284 | /// Get the current mode for mouse interaction or set's it
|
---|
285 | /// </summary>
|
---|
286 | public InteractiveModes InteractiveMode {
|
---|
287 | get {
|
---|
288 | return m_selectingMode;
|
---|
289 | }
|
---|
290 | set {
|
---|
291 | m_selectingMode = value;
|
---|
292 | m_oldSelectingMode = value;
|
---|
293 | //if (value == InteractiveModes.Rotating)
|
---|
294 | // m_axes[AxisNames.ZAxis].Visible = true;
|
---|
295 | //else if (value == InteractiveModes.ZoomRectangle)
|
---|
296 | // m_axes[AxisNames.ZAxis].Visible = false;
|
---|
297 | }
|
---|
298 | }
|
---|
299 | /// <summary>
|
---|
300 | /// Gives all graphs as value collection (readonly)
|
---|
301 | /// </summary>
|
---|
302 | public ILGraphCollection Graphs {
|
---|
303 | get {
|
---|
304 | if (m_graphs == null)
|
---|
305 | CreateControl();
|
---|
306 | return m_graphs;
|
---|
307 | }
|
---|
308 | }
|
---|
309 | /// <summary>
|
---|
310 | /// Get axes collection - holds all 3 axes
|
---|
311 | /// </summary>
|
---|
312 | public ILAxisCollection Axes {
|
---|
313 | get {
|
---|
314 | if (m_axes == null)
|
---|
315 | CreateControl();
|
---|
316 | return m_axes;
|
---|
317 | }
|
---|
318 | }
|
---|
319 | /// <summary>
|
---|
320 | /// (experimental) content for graphs will be clipped outside the unit cube
|
---|
321 | /// </summary>
|
---|
322 | /// <remarks>For 2D plots, not clipping the vertex data may lead to hiding
|
---|
323 | /// the labels drawn next to axes. For 3D plots Clipping may cause unexpected behavior.
|
---|
324 | /// <para>Therefore Clipping will be activated for 2D plots by default and
|
---|
325 | /// deactivated for 3D plots by default.</para></remarks>
|
---|
326 | public bool ClipViewData {
|
---|
327 | get {
|
---|
328 | return m_renderProperties.Clipping;
|
---|
329 | }
|
---|
330 | set {
|
---|
331 | m_renderProperties.Clipping = value;
|
---|
332 | }
|
---|
333 | }
|
---|
334 | /// <summary>
|
---|
335 | /// Manager providing collection of available IILTextRenderer types
|
---|
336 | /// </summary>
|
---|
337 | /// <remarks>IILTextRenderer are used to draw labels for axis of this panel (device specific).
|
---|
338 | /// <para>Text renderer objects must be instantiated through the ILTextRendererManager instance's
|
---|
339 | /// CreateInstance() method.</para></remarks>
|
---|
340 | public ILRendererManager TextRendererManager {
|
---|
341 | get {
|
---|
342 | return m_textRendererManager;
|
---|
343 | }
|
---|
344 | }
|
---|
345 | /// <summary>
|
---|
346 | /// Get or set default camera position for reset of the scene
|
---|
347 | /// </summary>
|
---|
348 | /// <remarks>The default position is used when the scene is reset. That
|
---|
349 | /// reset is usually triggered by double clicking the panel with the mouse.
|
---|
350 | /// <para>setting this value to null will make the panel ignore any double
|
---|
351 | /// clicks, which enables the user to manually react to double click via the
|
---|
352 | /// common DoubleClick event of the panel and reset the camera position from
|
---|
353 | /// outside the component.</para></remarks>
|
---|
354 | public ILCamera DefaultView {
|
---|
355 | get {
|
---|
356 | return m_defaultView;
|
---|
357 | }
|
---|
358 | protected set {
|
---|
359 | if (value != null) {
|
---|
360 | m_defaultView = value;
|
---|
361 | m_autoDefaultView = false;
|
---|
362 | } else {
|
---|
363 | m_autoDefaultView = true;
|
---|
364 | }
|
---|
365 | }
|
---|
366 | }
|
---|
367 | /// <summary>
|
---|
368 | /// Options for the view cube adapting data limit changes
|
---|
369 | /// </summary>
|
---|
370 | public AutoZoomOptions AutoZoomContent {
|
---|
371 | get {
|
---|
372 | return m_autoZoomOptions;
|
---|
373 | }
|
---|
374 | set {
|
---|
375 | m_autoZoomOptions = value;
|
---|
376 | }
|
---|
377 | }
|
---|
378 | /// <summary>
|
---|
379 | /// choose the ramp for zooming
|
---|
380 | /// </summary>
|
---|
381 | public ZoomModes ZoomMode {
|
---|
382 | get { return m_zoomMode; }
|
---|
383 | set { m_zoomMode = value; }
|
---|
384 | }
|
---|
385 | /// <summary>
|
---|
386 | /// How much the view cube will be shrinked/expanded on zooming operations (percent)
|
---|
387 | /// </summary>
|
---|
388 | public float ZoomOffset {
|
---|
389 | set { m_zoomOffset = value; }
|
---|
390 | get { return m_zoomOffset; }
|
---|
391 |
|
---|
392 | }
|
---|
393 | protected ILZoomAction ZoomAction {
|
---|
394 | get {
|
---|
395 | return m_zoomAction;
|
---|
396 | }
|
---|
397 | }
|
---|
398 | #endregion
|
---|
399 |
|
---|
400 | #region constructors
|
---|
401 | protected ILPanel(GraphicDeviceType graphicsDevice) : base () {
|
---|
402 | #if TRACE
|
---|
403 | Trace.TraceInformation("{0},{1} ILPanel.ctor()",DateTime.Now, Environment.TickCount);
|
---|
404 | #endif
|
---|
405 | this.DoubleBuffered = false;
|
---|
406 | //BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
---|
407 | m_plotBoxScreenSizeMode = PlotBoxScreenSizeMode.Optimal;
|
---|
408 | m_graphicsDevice = graphicsDevice;
|
---|
409 | m_textureManager = new ILTextureManager(m_graphicsDevice);
|
---|
410 | m_textureManager.DefaultHeight = 500;
|
---|
411 | m_textureManager.DefaultWidth = 500;
|
---|
412 | m_selectionRectangle = new ILLineProperties();
|
---|
413 | m_selectionRectangle.Antialiasing = false;
|
---|
414 | m_selectionRectangle.Color = Color.Blue;
|
---|
415 | m_selectionRectangle.Width = 1;
|
---|
416 | m_selectionRectangle.Style = LineStyle.Solid;
|
---|
417 | m_selectionRectangle.Changed += new EventHandler(m_selectionRectangle_Changed);
|
---|
418 | m_camera = new ILCamera((float)0.0f,0.0f,10.0f);
|
---|
419 | m_defaultView = new ILCamera(m_camera);
|
---|
420 | m_defaultView.Changed += new EventHandler(m_defaultView_Changed);
|
---|
421 | m_renderProperties = new ILRenderProperties ();
|
---|
422 | m_renderProperties.Camera = Camera;
|
---|
423 | m_textRendererManager = new ILRendererManager(this);
|
---|
424 | m_clippingView = new ILClippingData();
|
---|
425 | m_clippingView.AllowZeroVolume = false;
|
---|
426 | m_layoutData = new ILLayoutData(m_camera);
|
---|
427 | m_clippingView.Changed += new ILClippingDataChangedEvent(m_viewLimits_Changed);
|
---|
428 | m_colormap = new ILColormap();
|
---|
429 | m_colormap.Changed += new EventHandler(m_colormap_Changed);
|
---|
430 | Padding = new Padding(5);
|
---|
431 | BackColor = Color.White;
|
---|
432 | Dock = DockStyle.Fill;
|
---|
433 | m_legend = ILLegend.Create(this);
|
---|
434 | m_legend.Changed += new EventHandler(m_legend_Changed);
|
---|
435 | m_active = false;
|
---|
436 | m_ready = false;
|
---|
437 | }
|
---|
438 |
|
---|
439 | #endregion
|
---|
440 |
|
---|
441 | #region public interface function
|
---|
442 | /// <summary>
|
---|
443 | /// Dispose this panel, frees all devices, graph- and axis collection
|
---|
444 | /// </summary>
|
---|
445 | public new void Dispose () {
|
---|
446 | Dispose(false);
|
---|
447 | }
|
---|
448 | /// <summary>
|
---|
449 | /// dispose this panel
|
---|
450 | /// </summary>
|
---|
451 | /// <param name="disposing">manual disposing</param>
|
---|
452 | /// <remarks>derived classed (ILDXPanel,ILOGLPanel) free their resources here</remarks>
|
---|
453 | protected override void Dispose(bool disposing) {
|
---|
454 | #if TRACE
|
---|
455 | Trace.TraceInformation("{0},{1} ILPanel.Dispose(bool) start",DateTime.Now, Environment.TickCount);
|
---|
456 | Trace.Indent();
|
---|
457 | #endif
|
---|
458 | m_ready = false;
|
---|
459 | if (m_graphs != null)
|
---|
460 | m_graphs.Dispose();
|
---|
461 | if (m_axes != null)
|
---|
462 | m_axes.Dispose();
|
---|
463 | if (m_textureManager != null)
|
---|
464 | m_textureManager.Dispose();
|
---|
465 | base.Dispose(disposing);
|
---|
466 | #if TRACE
|
---|
467 | Trace.Unindent();
|
---|
468 | Trace.TraceInformation("{0},{1} ILPanel.Dispose(bool) end",DateTime.Now, Environment.TickCount);
|
---|
469 | #endif
|
---|
470 | }
|
---|
471 |
|
---|
472 | /// <summary>
|
---|
473 | /// causes the panel to redraw
|
---|
474 | /// </summary>
|
---|
475 | public override void Refresh() {
|
---|
476 | if (InvokeRequired) {
|
---|
477 | Invoke((MethodInvoker) delegate () { Refresh(); });
|
---|
478 | } else {
|
---|
479 | base.Refresh();
|
---|
480 | }
|
---|
481 | }
|
---|
482 | #endregion
|
---|
483 |
|
---|
484 | #region events
|
---|
485 | /// <summary>
|
---|
486 | /// fired, if the data limits of any graphs changed
|
---|
487 | /// </summary>
|
---|
488 | public event ILClippingDataChangedEvent DataLimitsChanged;
|
---|
489 | /// <summary>
|
---|
490 | /// fired, if the clipping rectangle for viewing graphs changed
|
---|
491 | /// </summary>
|
---|
492 | public event ILClippingDataChangedEvent ViewLimitsChanged;
|
---|
493 | /// <summary>
|
---|
494 | /// fires, if the current colormap has changed
|
---|
495 | /// </summary>
|
---|
496 | public event EventHandler ColormapChanged;
|
---|
497 | /// <summary>
|
---|
498 | /// fired, if the internal graphics device reset (Direct3D devices only)
|
---|
499 | /// </summary>
|
---|
500 | public event ILGraphicsDeviceResetEvent GraphicsDeviceReset;
|
---|
501 | /// <summary>
|
---|
502 | /// fired, if the internal graphics device has been (re)created
|
---|
503 | /// </summary>
|
---|
504 | public event ILGraphicsDeviceCreatedEvent GraphicsDeviceCreated;
|
---|
505 | #endregion
|
---|
506 |
|
---|
507 | #region event handlers
|
---|
508 | protected void m_defaultView_Changed(object sender, EventArgs e) {
|
---|
509 | m_autoDefaultView = false;
|
---|
510 | }
|
---|
511 | protected override void OnHandleCreated(EventArgs e) {
|
---|
512 | #if TRACE
|
---|
513 | Trace.TraceInformation("{0},{1} ILPanel.OnHandleCreated() start",DateTime.Now, Environment.TickCount);
|
---|
514 | Trace.Indent();
|
---|
515 | #endif
|
---|
516 | base.OnHandleCreated(e);
|
---|
517 | this.SetStyle(ControlStyles.AllPaintingInWmPaint,true);
|
---|
518 | this.SetStyle(ControlStyles.UserPaint,true);
|
---|
519 | #if TRACE
|
---|
520 | Trace.Unindent();
|
---|
521 | Trace.TraceInformation("{0},{1} ILPanel.OnHandleCreated() end",DateTime.Now, Environment.TickCount);
|
---|
522 | #endif
|
---|
523 | }
|
---|
524 | protected override void OnHandleDestroyed(EventArgs e) {
|
---|
525 | #if TRACE
|
---|
526 | Trace.TraceInformation("{0},{1} ILPanel.OnHandleDestroyed() start",DateTime.Now, Environment.TickCount);
|
---|
527 | Trace.Indent();
|
---|
528 | #endif
|
---|
529 | if (m_zoomAction != null) m_zoomAction.Cancel();
|
---|
530 | Dispose();
|
---|
531 | base.OnHandleDestroyed(e);
|
---|
532 | #if TRACE
|
---|
533 | Trace.Unindent();
|
---|
534 | Trace.TraceInformation("{0},{1} ILPanel.OnHandleDestroyed() end",DateTime.Now, Environment.TickCount);
|
---|
535 | #endif
|
---|
536 |
|
---|
537 | }
|
---|
538 | protected virtual void OnViewLimitsChanged(ClippingChangedEventArgs e) {
|
---|
539 | if (ViewLimitsChanged != null)
|
---|
540 | ViewLimitsChanged(this,e);
|
---|
541 | }
|
---|
542 | protected virtual void OnDataLimitsChanged(ClippingChangedEventArgs e) {
|
---|
543 | if (DataLimitsChanged != null)
|
---|
544 | DataLimitsChanged(this,e);
|
---|
545 | }
|
---|
546 | protected virtual void OnGraphicsDeviceReset() {
|
---|
547 | #if TRACE
|
---|
548 | Trace.TraceInformation("{0},{1} ILPanel.OnGraphicsDeviceReset() start",DateTime.Now, Environment.TickCount);
|
---|
549 | Trace.Indent();
|
---|
550 | #endif
|
---|
551 | Configure();
|
---|
552 | if (GraphicsDeviceReset != null) {
|
---|
553 | GraphicsDeviceReset(this,null);
|
---|
554 | }
|
---|
555 | #if TRACE
|
---|
556 | Trace.Unindent();
|
---|
557 | Trace.TraceInformation("{0},{1} ILPanel.OnGraphicsDeviceReset() end",DateTime.Now, Environment.TickCount);
|
---|
558 | #endif
|
---|
559 | }
|
---|
560 | protected virtual void OnGraphicsDeviceCreated() {
|
---|
561 | #if TRACE
|
---|
562 | Trace.TraceInformation("{0},{1} ILPanel.OnGraphicsDeviceCreated() start",DateTime.Now, Environment.TickCount);
|
---|
563 | Trace.Indent();
|
---|
564 | #endif
|
---|
565 | IILCreationFactory graphFact = GetCreationFactory();
|
---|
566 | m_graphs = new ILGraphCollection(graphFact);
|
---|
567 | m_graphs.CollectionChanged += new ILGraphCollectionChangedEvent(m_graphs_OnCollectionChanged);
|
---|
568 | m_graphs.Limits.Changed += new ILClippingDataChangedEvent(m_dataLimits_Changed);
|
---|
569 | m_graphs.GraphChanged += new ILGraphChangedEvent(m_graphs_GraphChanged);
|
---|
570 | m_axes = new ILAxisCollection(m_clippingView,graphFact);
|
---|
571 | if (GraphicsDeviceCreated!= null) {
|
---|
572 | GraphicsDeviceCreated(this,null);
|
---|
573 | }
|
---|
574 | //Invalidate();
|
---|
575 | #if TRACE
|
---|
576 | Trace.Unindent();
|
---|
577 | Trace.TraceInformation("{0},{1} ILPanel.OnGraphicsDeviceCreated() end",DateTime.Now, Environment.TickCount);
|
---|
578 | #endif
|
---|
579 | }
|
---|
580 |
|
---|
581 | protected virtual void OnColormapChanged() {
|
---|
582 | if (ColormapChanged != null)
|
---|
583 | ColormapChanged(this,null);
|
---|
584 | m_graphs.Invalidate();
|
---|
585 | }
|
---|
586 |
|
---|
587 | protected override void OnLostFocus(EventArgs e) {
|
---|
588 | base.OnLostFocus(e);
|
---|
589 | m_active = false;
|
---|
590 | }
|
---|
591 | protected override void OnGotFocus(EventArgs e) {
|
---|
592 | base.OnGotFocus(e);
|
---|
593 | m_active = true;
|
---|
594 | }
|
---|
595 | protected override void OnVisibleChanged(EventArgs e) {
|
---|
596 | if (IsHandleCreated && !IsDisposed) {
|
---|
597 | base.OnVisibleChanged(e);
|
---|
598 | if (Visible)
|
---|
599 | m_active = true;
|
---|
600 | else
|
---|
601 | m_active = false;
|
---|
602 | }
|
---|
603 | }
|
---|
604 | protected override void OnSizeChanged(EventArgs e) {
|
---|
605 | base.OnSizeChanged(e);
|
---|
606 | base.Invalidate();
|
---|
607 | }
|
---|
608 |
|
---|
609 | protected override void OnMouseMove(MouseEventArgs e) {
|
---|
610 | base.OnMouseMove(e);
|
---|
611 | if (m_selectingMode == InteractiveModes.Rotating) {
|
---|
612 | #region rotation
|
---|
613 | if (m_isDragging || (e.Button == System.Windows.Forms.MouseButtons.Left
|
---|
614 | && Math.Sqrt(Math.Pow(Math.Abs(e.X - m_mouseStart.X),2) + Math.Pow(Math.Abs(e.Y - m_mouseStart.Y),2)) > 3.0)) {
|
---|
615 | m_isDragging = true;
|
---|
616 | m_camera.EventingSuspend();
|
---|
617 | int distX = e.Location.X - m_mouseStart.X;
|
---|
618 | int distY = e.Location.Y - m_mouseStart.Y;
|
---|
619 | float tmp = m_camera.Phi - distX / 200.0f;
|
---|
620 | // if alt is pressed, lock on even angles
|
---|
621 | if (((Control.ModifierKeys & Keys.Alt) != 0)
|
---|
622 | && (Math.Abs(Math.Round(tmp/pi4) - (tmp / pi4)) < 0.05)) {
|
---|
623 | tmp = (float)(Math.Round(tmp / pi4) * pi4);
|
---|
624 | }
|
---|
625 | m_camera.Phi = tmp;
|
---|
626 | tmp = m_camera.Rho - distY / 200.0f;
|
---|
627 | // if alt is pressed, lock on even angles
|
---|
628 | if (((Control.ModifierKeys & Keys.Alt) != 0)
|
---|
629 | && (Math.Abs(Math.Round(tmp/pi8) - (tmp / pi8)) < 0.05)) {
|
---|
630 | tmp = (float)(Math.Round(tmp / pi8) * pi8);
|
---|
631 | }
|
---|
632 | m_camera.Rho = tmp;
|
---|
633 | if (m_camera.Rho > Math.PI) m_camera.Rho = (float)Math.PI;
|
---|
634 | if (m_camera.Rho < 0) m_camera.Rho = 0.0f;
|
---|
635 | m_camera.EventingResume();
|
---|
636 | m_mouseStart = e.Location;
|
---|
637 | Refresh();
|
---|
638 | }
|
---|
639 | #endregion
|
---|
640 | } else if (m_selectingMode == InteractiveModes.ZoomRectangle) {
|
---|
641 | #region selection rectangle
|
---|
642 | if (m_isDragging || (e.Button == System.Windows.Forms.MouseButtons.Left
|
---|
643 | && Math.Sqrt(Math.Pow(Math.Abs(e.X - m_mouseStart.X),2) + Math.Pow(Math.Abs(e.Y - m_mouseStart.Y),2)) > 3.0)) {
|
---|
644 | m_isDragging = true;
|
---|
645 | Cursor = Cursors.Cross;
|
---|
646 | Refresh();
|
---|
647 | }
|
---|
648 | #endregion
|
---|
649 | } else if (m_selectingMode == InteractiveModes.Translating) {
|
---|
650 | if (m_isDragging || (e.Button == System.Windows.Forms.MouseButtons.Left
|
---|
651 | && Math.Sqrt(Math.Pow(Math.Abs(e.X - m_mouseStart.X),2) + Math.Pow(Math.Abs(e.Y - m_mouseStart.Y),2)) > 1.0)) {
|
---|
652 | ILPoint3Df p1,p2,dummy;
|
---|
653 | Screen2World(m_mouseStart.X,Height - m_mouseStart.Y, out p1, out dummy);
|
---|
654 | Screen2World(e.X, Height - e.Y, out p2, out dummy);
|
---|
655 | if (m_projection == Projection.Perspective) {
|
---|
656 | p1 = ILPoint3Df.normalize(p1 - m_camera.Position) * m_camera.Distance;
|
---|
657 | p2 = ILPoint3Df.normalize(p2 - m_camera.Position) * m_camera.Distance;
|
---|
658 | }
|
---|
659 | p1 = p2 - p1;
|
---|
660 | m_camera.LookAt -= p1;
|
---|
661 | m_mouseStart = e.Location;
|
---|
662 | Refresh();
|
---|
663 | }
|
---|
664 |
|
---|
665 | }
|
---|
666 | }
|
---|
667 | protected override void OnMouseUp(MouseEventArgs e) {
|
---|
668 | base.OnMouseUp(e);
|
---|
669 | //System.Diagnostic.Debug.WriteLine("MouseUp");
|
---|
670 | if (m_selectingMode == InteractiveModes.ZoomRectangle && m_isDragging) {
|
---|
671 | Zoom(Screen2World2D(m_mouseStart.X,Height - m_mouseStart.Y),Screen2World2D(e.X, Height - e.Y));
|
---|
672 | }
|
---|
673 | m_isDragging = false;
|
---|
674 | Cursor = Cursors.Default;
|
---|
675 | }
|
---|
676 | protected override void OnMouseDown(MouseEventArgs e) {
|
---|
677 | base.OnMouseDown(e);
|
---|
678 | m_mouseStart = e.Location;
|
---|
679 | }
|
---|
680 | protected override void OnMouseClick(MouseEventArgs e) {
|
---|
681 | base.OnMouseClick(e);
|
---|
682 | //System.Diagnostic.Debug.WriteLine("Click");
|
---|
683 | if (m_isDragging == false && (m_selectingMode == InteractiveModes.ZoomRectangle
|
---|
684 | || m_selectingMode == InteractiveModes.Rotating)) {
|
---|
685 | // determine new center coords
|
---|
686 | ILPoint3Df near, far;
|
---|
687 | Screen2World(e.X,Height - e.Y, out near, out far); //Limits.CenterF.Z);
|
---|
688 | if (e.Button == System.Windows.Forms.MouseButtons.Left) {
|
---|
689 | Zoom(near,far,m_zoomOffset / 100);
|
---|
690 | }
|
---|
691 | else if (e.Button == System.Windows.Forms.MouseButtons.Right)
|
---|
692 | Zoom(near,far,- m_zoomOffset / 100);
|
---|
693 | }
|
---|
694 | }
|
---|
695 | protected override void OnMouseDoubleClick(MouseEventArgs e) {
|
---|
696 | base.OnMouseDoubleClick(e);
|
---|
697 | ResetView(true);
|
---|
698 | Refresh();
|
---|
699 | }
|
---|
700 | protected override void OnKeyDown(KeyEventArgs e) {
|
---|
701 | if (e.Control && !m_isCtrlKeyDown) {
|
---|
702 | m_oldSelectingMode = m_selectingMode;
|
---|
703 | m_selectingMode = InteractiveModes.Translating;
|
---|
704 | m_isCtrlKeyDown = true;
|
---|
705 | Cursor = Cursors.NoMove2D;
|
---|
706 | //m_isDragging = false;
|
---|
707 | }
|
---|
708 | base.OnKeyDown(e);
|
---|
709 | }
|
---|
710 | protected override void OnKeyUp(KeyEventArgs e) {
|
---|
711 | if (!e.Control) {
|
---|
712 | if (m_isCtrlKeyDown) {
|
---|
713 | m_isCtrlKeyDown = false;
|
---|
714 | m_selectingMode = m_oldSelectingMode;
|
---|
715 | }
|
---|
716 | Cursor = Cursors.Default;
|
---|
717 | //m_isDragging = false;
|
---|
718 | }
|
---|
719 | base.OnKeyUp(e);
|
---|
720 | }
|
---|
721 | protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) {
|
---|
722 | if (DesignMode) {
|
---|
723 | e.Graphics.Clear(Color.LightBlue);
|
---|
724 | return;
|
---|
725 | }
|
---|
726 | if (e.ClipRectangle.Width == 0 || e.ClipRectangle.Height == 0) {
|
---|
727 | #if TRACE
|
---|
728 | Trace.TraceInformation("{0},{1} ILPanel.OnPaint(): ClipRectangle.Size = empty -> skipping",DateTime.Now, Environment.TickCount);
|
---|
729 | #endif
|
---|
730 | return;
|
---|
731 | }
|
---|
732 | /* THIS IS PRELIMINARY IMPLEMENTATION! REASON: While using GDI renderer,
|
---|
733 | * it is importatnt, to have the whole (visible) surface area invalidated
|
---|
734 | * and available for clipping of the graphics objects in 'e'. Otherwise
|
---|
735 | * rendered objects will not show, after the buffers have swapped. The
|
---|
736 | * following code helps pick those situations, where the clipping region
|
---|
737 | * is only a subregion of the controls surface, but it introduces new
|
---|
738 | * problems, if the whole control is (partially) obscured by other controls.
|
---|
739 | * Since the GDI Renderer currently is not the recommended method of rendering,
|
---|
740 | * this code is commented until a better solution was found. */
|
---|
741 | // if (e.ClipRectangle.X > 0 || e.ClipRectangle.Y > 0) {
|
---|
742 | //#if TRACE
|
---|
743 | // Trace.TraceInformation("{0},{1} ILPanel.OnPaint(): partial clipping detected -> refreshing whole controls area",DateTime.Now, Environment.TickCount);
|
---|
744 | //#endif
|
---|
745 | // Refresh();
|
---|
746 | // return;
|
---|
747 | // }
|
---|
748 | try {
|
---|
749 | #if TRACE
|
---|
750 | Trace.TraceInformation("{0},{1} ILPanel.OnPaint(): started (re-)configure",DateTime.Now, Environment.TickCount);
|
---|
751 | Trace.Indent();
|
---|
752 | #endif
|
---|
753 | Configure();
|
---|
754 | if (m_isStartingUp && (m_autoZoomOptions != AutoZoomOptions.Never)) {
|
---|
755 | ResetView(true);
|
---|
756 | }
|
---|
757 | #if TRACE
|
---|
758 | Trace.Unindent();
|
---|
759 | Trace.TraceInformation("{0},{1} ILPanel.OnPaint(): rendering started",DateTime.Now, Environment.TickCount);
|
---|
760 | Trace.Indent();
|
---|
761 | Trace.TraceInformation(String.Format("this: {1}, ClipRectangle: {0}, Graphics.ClipBounds: L:{2} T:{3} W:{4} H:{5}"
|
---|
762 | ,e.ClipRectangle.ToString()
|
---|
763 | ,this.ClientRectangle.ToString()
|
---|
764 | ,e.Graphics.VisibleClipBounds.Left
|
---|
765 | ,e.Graphics.VisibleClipBounds.Top
|
---|
766 | ,e.Graphics.VisibleClipBounds.Width
|
---|
767 | ,e.Graphics.VisibleClipBounds.Height));
|
---|
768 | #endif
|
---|
769 | m_renderProperties.Graphics = e.Graphics;
|
---|
770 | m_renderProperties.Reason = RenderReason.PaintEvent;
|
---|
771 | m_renderProperties.MinX = int.MaxValue;
|
---|
772 | m_renderProperties.MinY = int.MaxValue;
|
---|
773 | m_renderProperties.MaxX = int.MinValue;
|
---|
774 | m_renderProperties.MaxY = int.MinValue;
|
---|
775 | RenderScene(m_renderProperties.Reset());
|
---|
776 | #if TRACE
|
---|
777 | Trace.Unindent();
|
---|
778 | Trace.TraceInformation("{0},{1} ILPanel.OnPaint(): rendering ended",DateTime.Now, Environment.TickCount);
|
---|
779 | #endif
|
---|
780 | if (m_isStartingUp) {
|
---|
781 | m_isStartingUp = false;
|
---|
782 | Refresh();
|
---|
783 | }
|
---|
784 | System.Diagnostics.Debug.WriteLine("Current Camera Setting: " + m_camera.ToString());
|
---|
785 | } catch (Exceptions.ILArgumentException exc) {
|
---|
786 | #if TRACE
|
---|
787 | Trace.TraceWarning("{0},{1} ILPanel.OnPaint(): rendering failed. reason: {2}",DateTime.Now, Environment.TickCount,exc.ToString());
|
---|
788 | Trace.Indent();
|
---|
789 | #endif
|
---|
790 | System.Diagnostics.Debug.WriteLine("ILPanel.OnPaint failed: " + exc.ToString());
|
---|
791 | throw new Exceptions.ILArgumentException("rendering failed. Details attached.",exc);
|
---|
792 | }
|
---|
793 | }
|
---|
794 | void m_legend_Changed(object sender, EventArgs e) {
|
---|
795 | Invalidate();
|
---|
796 | }
|
---|
797 |
|
---|
798 | void m_graphs_GraphChanged(object sender, ILGraphChangedEventArgs args) {
|
---|
799 | ResetView(false);
|
---|
800 | }
|
---|
801 | protected void m_graphs_OnCollectionChanged(object sender, ILGraphCollectionChangedEventArgs args) {
|
---|
802 | if (args.Reason == GraphCollectionChangeReason.Added) {
|
---|
803 | if (AutoDefaultView && (args.Configurator != null)) {
|
---|
804 | args.Configurator.ConfigurePanel(this);
|
---|
805 | }
|
---|
806 | }
|
---|
807 | }
|
---|
808 | protected void m_viewLimits_Changed(object sender, ClippingChangedEventArgs e) {
|
---|
809 | if (this.InvokeRequired && IsHandleCreated) {
|
---|
810 | try {
|
---|
811 | Invoke(new ILClippingDataChangedEvent(m_viewLimits_Changed), sender, e);
|
---|
812 | } catch (Exception) { }
|
---|
813 | } else {
|
---|
814 | m_camera.LookAt = m_clippingView.CenterF;
|
---|
815 | OnViewLimitsChanged(e);
|
---|
816 | }
|
---|
817 | }
|
---|
818 | protected void m_dataLimits_Changed(object sender, ClippingChangedEventArgs e) {
|
---|
819 | if (m_autoDefaultView) {
|
---|
820 | m_defaultView.EventingSuspend();
|
---|
821 | bool oldDefaultViewSetting = m_autoDefaultView;
|
---|
822 | m_defaultView.LookAt = m_graphs.Limits.CenterF;
|
---|
823 | m_defaultView.Distance = m_graphs.Limits.SphereRadius * 2;
|
---|
824 | m_defaultView.EventingResume(false);
|
---|
825 | }
|
---|
826 | if (m_autoZoomOptions == AutoZoomOptions.OnDataChanges)
|
---|
827 | ResetView(false);
|
---|
828 | OnDataLimitsChanged(e);
|
---|
829 | }
|
---|
830 |
|
---|
831 | protected void m_colormap_Changed(object sender, EventArgs e) {
|
---|
832 | OnColormapChanged();
|
---|
833 | }
|
---|
834 | void m_selectionRectangle_Changed(object sender, EventArgs e) {
|
---|
835 | // nothing to do here
|
---|
836 | }
|
---|
837 |
|
---|
838 | #endregion event handler
|
---|
839 |
|
---|
840 | #region virtual abstract interface
|
---|
841 | /// <summary>
|
---|
842 | /// Get current rendering device (implementation dependent)
|
---|
843 | /// </summary>
|
---|
844 | /// <returns></returns>
|
---|
845 | public abstract object GetDeviceContext();
|
---|
846 | /// <summary>
|
---|
847 | /// Causes a reconfiguration of all axes and graphs on the next paint event
|
---|
848 | /// </summary>
|
---|
849 | /// <remarks>Call this method after any changes to vertex relevant data. It causes all drawable objects to clear their caches and recalculate all vertex data.</remarks>
|
---|
850 | protected new void Invalidate() {
|
---|
851 | if (!m_ready) return;
|
---|
852 | m_ready = false;
|
---|
853 | m_graphs.Invalidate();
|
---|
854 | m_axes.Invalidate();
|
---|
855 | //base.Invalidate(this.ClientRectangle, true); <- this would cause an immediate redraw also. Use Refresh() for this!
|
---|
856 | }
|
---|
857 | /// <summary>
|
---|
858 | /// update viewing limits to show all data, rotate the scene to default (-> DefaultView)
|
---|
859 | /// </summary>
|
---|
860 | public virtual void ResetView() {
|
---|
861 | ResetView(true);
|
---|
862 | }
|
---|
863 | /// <summary>
|
---|
864 | /// update viewing limits to show all data, optionally reset the scene rotation
|
---|
865 | /// </summary>
|
---|
866 | /// <param name="resetRotation">true: rotate the scene to the default (-> DefaultView)</param>
|
---|
867 | public virtual void ResetView(bool resetRotation) {
|
---|
868 | if (m_zoomAction != null)
|
---|
869 | m_zoomAction.Cancel();
|
---|
870 | m_clippingView.EventingSuspend();
|
---|
871 | m_clippingView.CopyFrom(m_graphs.Limits);
|
---|
872 | m_clippingView.Update(m_clippingView.CenterF,1.1f);
|
---|
873 | m_clippingView.EventingResume();
|
---|
874 | if (m_defaultView != null && resetRotation) {
|
---|
875 | m_camera.LookAt = m_defaultView.LookAt;
|
---|
876 | m_camera.Phi = m_defaultView.Phi;
|
---|
877 | m_camera.Rho = m_defaultView.Rho;
|
---|
878 | m_camera.Distance = m_defaultView.Distance;
|
---|
879 | }
|
---|
880 | }
|
---|
881 | /// <summary>
|
---|
882 | /// Move & shrink/expand current view cube along a given line
|
---|
883 | /// </summary>
|
---|
884 | /// <param name="nearLineEnd"></param>
|
---|
885 | /// <param name="farLineEnd"></param>
|
---|
886 | /// <param name="offset"></param>
|
---|
887 | protected virtual void Zoom(ILPoint3Df nearLineEnd, ILPoint3Df farLineEnd, float offset) {
|
---|
888 | ILPoint3Df minCorner, maxCorner;
|
---|
889 | m_clippingView.GetZoomParameter(nearLineEnd,farLineEnd,offset, out minCorner, out maxCorner);
|
---|
890 | Zoom(minCorner,maxCorner);
|
---|
891 | //m_camera.LookAt = m_clippingView.CenterF;
|
---|
892 | }
|
---|
893 | /// <summary>
|
---|
894 | /// move the center of the viewing cube and expand / shrink the volume by offset
|
---|
895 | /// </summary>
|
---|
896 | /// <param name="center">new center</param>
|
---|
897 | /// <param name="offset">offset multiplicator, 1f means: no change</param>
|
---|
898 | protected virtual void Zoom(ILPoint3Df center, float offset) {
|
---|
899 | m_clippingView.Update(center,offset);
|
---|
900 | Refresh();
|
---|
901 | }
|
---|
902 | /// <summary>
|
---|
903 | /// Zoome the scene to new limits
|
---|
904 | /// </summary>
|
---|
905 | /// <param name="luCorner">'upper left' (first) corner of the new viewing cube</param>
|
---|
906 | /// <param name="rbCorner">'bottom right' (opposed) corner of the viewing cube</param>
|
---|
907 | protected virtual void Zoom(ILPoint3Df luCorner, ILPoint3Df rbCorner) {
|
---|
908 | if (m_zoomAction != null)
|
---|
909 | m_zoomAction.Cancel();
|
---|
910 | ILActionRamp ramp;
|
---|
911 | switch (m_zoomMode) {
|
---|
912 | case ZoomModes.Jump:
|
---|
913 | ramp = ILActionRamp.NoRamp;
|
---|
914 | break;
|
---|
915 | case ZoomModes.RollSoft:
|
---|
916 | ramp = ILActionRamp.Soft;
|
---|
917 | break;
|
---|
918 | case ZoomModes.RollHard:
|
---|
919 | ramp = ILActionRamp.Hard;
|
---|
920 | break;
|
---|
921 | case ZoomModes.RollOverride:
|
---|
922 | ramp = ILActionRamp.Override;
|
---|
923 | break;
|
---|
924 | default:
|
---|
925 | ramp = ILActionRamp.Linear;
|
---|
926 | break;
|
---|
927 | }
|
---|
928 | m_zoomAction = new ILZoomAction(m_clippingView.Min, luCorner, m_clippingView.Max, rbCorner, ramp, this);
|
---|
929 | m_zoomAction.Run();
|
---|
930 | }
|
---|
931 |
|
---|
932 |
|
---|
933 | /// <summary>
|
---|
934 | /// Transform two coordinates for a line from world to screen coordinates
|
---|
935 | /// </summary>
|
---|
936 | /// <param name="start">1st coordinate (world)</param>
|
---|
937 | /// <param name="end">2nd coordinate (world)</param>
|
---|
938 | /// <param name="start2D">[output] 1st coordinate (screen pixels)</param>
|
---|
939 | /// <param name="end2D">[output] 2nd coordinate (screen pixels)</param>
|
---|
940 | /// <remarks>This function is provided by the concrete derived class, using the
|
---|
941 | /// current rendering framework.</remarks>
|
---|
942 | public abstract void World2Screen(ILPoint3Df start, ILPoint3Df end, out Point start2D, out Point end2D);
|
---|
943 |
|
---|
944 | /// <summary>
|
---|
945 | /// Transform from a point on screen into world coordinates [depricated]
|
---|
946 | /// </summary>
|
---|
947 | /// <param name="x">screen x</param>
|
---|
948 | /// <param name="y">screen y: GL viewport coord! -> (0,0) is lower left corner!</param>
|
---|
949 | /// <returns>world coordinate point</returns>
|
---|
950 | public abstract ILPoint3Df Screen2World2D(int x, int y);
|
---|
951 | /// <summary>
|
---|
952 | /// gives the line in world coords, a specific point on screen lays on
|
---|
953 | /// </summary>
|
---|
954 | /// <param name="x">screen x</param>
|
---|
955 | /// <param name="y">screen y: GL viewport coord! -> (0,0) is lower left corner</param>
|
---|
956 | /// <param name="farClip">far end point of the resulting line in world coords</param>
|
---|
957 | /// <param name="nearClip">near end point of the resulting line in world coords</param>
|
---|
958 | public abstract void Screen2World(int x, int y, out ILPoint3Df nearClip, out ILPoint3Df farClip);
|
---|
959 |
|
---|
960 | /// <summary>
|
---|
961 | /// Transform world coordinate to screen coordinate under current transformation
|
---|
962 | /// </summary>
|
---|
963 | /// <param name="worldPoint">world coordinate</param>
|
---|
964 | /// <returns>screen location</returns>
|
---|
965 | /// <remarks>the actual transform is carried out in the derived specialized class,
|
---|
966 | /// where the current transformation matrices are known</remarks>
|
---|
967 | public abstract Point World2Screen(ILPoint3Df worldPoint);
|
---|
968 | /// <summary>
|
---|
969 | /// Transform world coordinate to screen coordinate, provide (custom) modelview matrix
|
---|
970 | /// </summary>
|
---|
971 | /// <param name="worldPoint"></param>
|
---|
972 | /// <param name="modelview">(custom) model view matrix. The parameter must match the format required by the deriving concrete ILPanel class. ILOGLPanel: double[16]</param>
|
---|
973 | /// <returns>screen location</returns>
|
---|
974 | /// <remarks>the actual transform is carried out in the derived specialized class,
|
---|
975 | /// where the current transformation matrices are known</remarks>
|
---|
976 | public abstract Point World2Screen(ILPoint3Df worldPoint, double[] modelview);
|
---|
977 |
|
---|
978 | /// <summary>
|
---|
979 | /// Draws content of this subfigure into predefined bitmap
|
---|
980 | /// </summary>
|
---|
981 | /// <param name="bitmap">predefined bitmap to draw content into. The size must have been initialized according to 'bounds'.</param>
|
---|
982 | /// <param name="bounds">Rectangle specifying the region to be copied.</param>
|
---|
983 | public new abstract void DrawToBitmap(Bitmap bitmap, Rectangle bounds);
|
---|
984 | #endregion
|
---|
985 |
|
---|
986 | #region helper functions
|
---|
987 | /// <summary>
|
---|
988 | /// draws the selection rectangle with GDI functions
|
---|
989 | /// </summary>
|
---|
990 | /// <param name="endPoint">end point</param>
|
---|
991 | /// <remarks>The start point is stored in the member m_mouseStart.</remarks>
|
---|
992 | protected virtual void drawSelectionRect(Point endPoint) {
|
---|
993 | Graphics g = Graphics.FromHwnd(this.Handle);
|
---|
994 | Pen pen = new Pen(m_selectionRectangle.Color, 1.0f);
|
---|
995 | Point[] points = new Point[3];
|
---|
996 | // upper left corner
|
---|
997 | points[0] = new Point(m_mouseStart.X, m_mouseStart.Y + (endPoint.Y - m_mouseStart.Y) / 4);
|
---|
998 | points[1] = new Point(m_mouseStart.X, m_mouseStart.Y);
|
---|
999 | points[2] = new Point(m_mouseStart.X + (endPoint.X - m_mouseStart.X) / 4, m_mouseStart.Y);
|
---|
1000 | g.DrawLines(pen, points);
|
---|
1001 | // lower left corner
|
---|
1002 | points[0] = new Point(m_mouseStart.X, endPoint.Y - (endPoint.Y - m_mouseStart.Y) / 4);
|
---|
1003 | points[1] = new Point(m_mouseStart.X, endPoint.Y);
|
---|
1004 | points[2] = new Point(m_mouseStart.X + (endPoint.X - m_mouseStart.X) / 4, endPoint.Y);
|
---|
1005 | g.DrawLines(pen, points);
|
---|
1006 | // lower right corner
|
---|
1007 | points[0] = new Point(endPoint.X, endPoint.Y - (endPoint.Y - m_mouseStart.Y) / 4);
|
---|
1008 | points[1] = new Point(endPoint.X, endPoint.Y);
|
---|
1009 | points[2] = new Point(endPoint.X - (endPoint.X - m_mouseStart.X) / 4, endPoint.Y);
|
---|
1010 | g.DrawLines(pen, points);
|
---|
1011 | // upper right corner
|
---|
1012 | points[0] = new Point(endPoint.X, m_mouseStart.Y + (endPoint.Y - m_mouseStart.Y) / 4);
|
---|
1013 | points[1] = new Point(endPoint.X, m_mouseStart.Y);
|
---|
1014 | points[2] = new Point(endPoint.X - (endPoint.X - m_mouseStart.X) / 4, m_mouseStart.Y);
|
---|
1015 | g.DrawLines(pen, points);
|
---|
1016 | }
|
---|
1017 | public static short StippleFromLineStyle(LineStyle style, ref int stipFactr) {
|
---|
1018 | short ret = 1;
|
---|
1019 | switch (style) {
|
---|
1020 | case LineStyle.Dashed:
|
---|
1021 | ret = (short)255;
|
---|
1022 | stipFactr = 2;
|
---|
1023 | break;
|
---|
1024 | case LineStyle.PointDash:
|
---|
1025 | ret = (short)255 + 4096;
|
---|
1026 | stipFactr = 1;
|
---|
1027 | break;
|
---|
1028 | case LineStyle.Dotted:
|
---|
1029 | ret = (short)13107; // 3 + 48 + 768 + 8192 + 4096;
|
---|
1030 | stipFactr = 2;
|
---|
1031 | break;
|
---|
1032 | case LineStyle.UserPattern:
|
---|
1033 | break;
|
---|
1034 | // ret = 0;
|
---|
1035 | case LineStyle.None:
|
---|
1036 | break;
|
---|
1037 | default: // solid
|
---|
1038 | ret = (short)-1;
|
---|
1039 | break;
|
---|
1040 | }
|
---|
1041 | return ret;
|
---|
1042 | }
|
---|
1043 | private void calculateDefaultView(bool setPositions, bool setDirection) {
|
---|
1044 | m_defaultView.EventingSuspend();
|
---|
1045 | if (setPositions) {
|
---|
1046 | m_defaultView.LookAt = m_graphs.Limits.CenterF;
|
---|
1047 | m_defaultView.Distance = m_clippingView.SphereRadius * 2f;
|
---|
1048 | }
|
---|
1049 | if (setDirection) {
|
---|
1050 | m_defaultView.Phi = 0; // -(float)Math.PI / 2;
|
---|
1051 | m_defaultView.Rho = 0;
|
---|
1052 | }
|
---|
1053 | m_defaultView.EventingResume(false);
|
---|
1054 | }
|
---|
1055 | #endregion
|
---|
1056 |
|
---|
1057 | #region private rendering setup helper
|
---|
1058 | protected void helperUpdateMatrices(float width2D, float height2D, out float worldSceneWidth, out float worldSceneHeight, out ILPoint3Df top, out ILPoint3Df moveOffset)
|
---|
1059 | {
|
---|
1060 | float localPlotCubeScreenRectLeft;
|
---|
1061 | float localPlotCubeScreenRectWidth;
|
---|
1062 |
|
---|
1063 | float localPlotCubeScreenRectTop;
|
---|
1064 | float localPlotCubeScreenRectHeight;
|
---|
1065 |
|
---|
1066 | float offsetX;
|
---|
1067 | float offsetY;
|
---|
1068 |
|
---|
1069 | localPlotCubeScreenRectHeight = m_plotBoxScreenRectF.Height;
|
---|
1070 | localPlotCubeScreenRectWidth = m_plotBoxScreenRectF.Width;
|
---|
1071 | localPlotCubeScreenRectTop = m_plotBoxScreenRectF.Top;
|
---|
1072 | localPlotCubeScreenRectLeft = m_plotBoxScreenRectF.Left;
|
---|
1073 |
|
---|
1074 | if (AspectRatio == AspectRatioMode.StretchToFill)
|
---|
1075 | {
|
---|
1076 | worldSceneWidth = width2D / localPlotCubeScreenRectWidth;
|
---|
1077 | worldSceneHeight = height2D / localPlotCubeScreenRectHeight;
|
---|
1078 | }
|
---|
1079 | else
|
---|
1080 | { //if (RenderAspectRatioMode == RenderAspectRatioMode.MaintainRatios) {
|
---|
1081 | float plotCubeScreenRectAspectRatio =
|
---|
1082 | (m_plotBoxScreenRectF.Width * ClientSize.Width)
|
---|
1083 | / (m_plotBoxScreenRectF.Height * ClientSize.Height);
|
---|
1084 | float dataAspectRatio = width2D / height2D;
|
---|
1085 | if (plotCubeScreenRectAspectRatio > dataAspectRatio)
|
---|
1086 | {
|
---|
1087 | // width > height
|
---|
1088 | worldSceneHeight = height2D;
|
---|
1089 | worldSceneWidth = worldSceneHeight * dataAspectRatio;
|
---|
1090 | // enlarge the scene, so we have rendering margin outside the data cube
|
---|
1091 | worldSceneHeight /= localPlotCubeScreenRectHeight;
|
---|
1092 | worldSceneWidth /= (localPlotCubeScreenRectWidth * (dataAspectRatio / plotCubeScreenRectAspectRatio));
|
---|
1093 | }
|
---|
1094 | else
|
---|
1095 | {
|
---|
1096 | // height >= width
|
---|
1097 | worldSceneWidth = width2D;
|
---|
1098 | worldSceneHeight = worldSceneWidth / dataAspectRatio;
|
---|
1099 | // enlarge the scene, so we have rendering margin outside the data cube
|
---|
1100 | worldSceneWidth /= localPlotCubeScreenRectWidth;
|
---|
1101 | worldSceneHeight /= (localPlotCubeScreenRectHeight / (dataAspectRatio / plotCubeScreenRectAspectRatio));
|
---|
1102 | }
|
---|
1103 | }
|
---|
1104 | // one more pixel please...
|
---|
1105 | worldSceneHeight = (worldSceneHeight / ClientSize.Height * (ClientSize.Height + 1));
|
---|
1106 | worldSceneWidth = (worldSceneWidth / ClientSize.Width * (ClientSize.Width + 1));
|
---|
1107 | // if PlotCubeScreenRect is not centered, we move the scene out of center accordingly (..further down)
|
---|
1108 | top = new ILPoint3Df(-m_camera.SinPhi * m_camera.CosRho, m_camera.CosPhi * m_camera.CosRho, m_camera.SinRho);
|
---|
1109 | ILPoint3Df moveX = ILPoint3Df.crossN(m_camera.Position - m_camera.LookAt, top);
|
---|
1110 | offsetX = -(localPlotCubeScreenRectLeft + (localPlotCubeScreenRectWidth / 2f) - 0.5f) * worldSceneWidth;
|
---|
1111 | offsetY = -(localPlotCubeScreenRectTop + (localPlotCubeScreenRectHeight / 2f) - 0.5f) * worldSceneHeight;
|
---|
1112 | moveOffset = top * offsetY + moveX * offsetX;
|
---|
1113 | }
|
---|
1114 | protected virtual void RenderScene(ILRenderProperties p) {
|
---|
1115 | //System.Diagnostics.Debug.Print("m_camera:{0}", m_camera);
|
---|
1116 | if (!DesignMode) {
|
---|
1117 | lock (m_sortingCacheList) {
|
---|
1118 | iRenderingState1(p); //make current
|
---|
1119 | // configure axes (determine tick labels in mode 'auto')
|
---|
1120 | m_axes.XAxis.Configure(p);
|
---|
1121 | m_axes.YAxis.Configure(p);
|
---|
1122 | m_axes.ZAxis.Configure(p);
|
---|
1123 |
|
---|
1124 |
|
---|
1125 | //computeLayoutData(p);
|
---|
1126 | float rotatedViewLimitX, rotatedViewLimitY, rotatedViewLimitZ;
|
---|
1127 | GetTransformedSize(out rotatedViewLimitX, out rotatedViewLimitY, out rotatedViewLimitZ);
|
---|
1128 |
|
---|
1129 | // determine needed margins according to current tic label collections (which are left over from last rendering run or empty)
|
---|
1130 | Size ticLabelsMargins = GetMaxTicLabelSize(p.Graphics);
|
---|
1131 | updatePlotCubeScreenRect(rotatedViewLimitX, rotatedViewLimitY, ticLabelsMargins);
|
---|
1132 | p.PassCount = 0;
|
---|
1133 | for (; p.PassCount < MAXRENDERPASSES; p.PassCount++) {
|
---|
1134 | UpdateMatrices(rotatedViewLimitX, rotatedViewLimitY, rotatedViewLimitZ);
|
---|
1135 |
|
---|
1136 | updateTickLabelLines();
|
---|
1137 | updateLabelPositions(p);
|
---|
1138 | if (p.PassCount == 0) {
|
---|
1139 | }
|
---|
1140 | iRenderingState2(p); // do the actual drawing
|
---|
1141 | //iRenderingState3(p);
|
---|
1142 | #region check if we can fit the plot cube more precisely
|
---|
1143 | if (m_plotBoxScreenSizeMode == PlotBoxScreenSizeMode.StrictOptimal) {
|
---|
1144 | float t = m_plotBoxScreenRectF.Top;
|
---|
1145 | float l = m_plotBoxScreenRectF.Left;
|
---|
1146 | float r = m_plotBoxScreenRectF.Right;
|
---|
1147 | float b = m_plotBoxScreenRectF.Bottom, tmp;
|
---|
1148 | bool resize = false;
|
---|
1149 | tmp = (float)p.MinX / ClientSize.Width;
|
---|
1150 | if (tmp < l) {
|
---|
1151 | if (p.MinX != 0) {
|
---|
1152 | l -= tmp;
|
---|
1153 | resize = true;
|
---|
1154 | }
|
---|
1155 | } else if (l > 0) {
|
---|
1156 | l = 0;
|
---|
1157 | resize = true;
|
---|
1158 | }
|
---|
1159 | tmp = (float)p.MaxX / ClientSize.Width;
|
---|
1160 | if (tmp > r) {
|
---|
1161 | if (p.MaxX != (ClientSize.Width - 1)) {
|
---|
1162 | r += (1 - tmp);
|
---|
1163 | resize = true;
|
---|
1164 | }
|
---|
1165 | } else if (r < 1) {
|
---|
1166 | r = (float)(ClientSize.Width - 1) / ClientSize.Width;
|
---|
1167 | resize = true;
|
---|
1168 | }
|
---|
1169 | tmp = (float)p.MinY / ClientSize.Height;
|
---|
1170 | if (tmp < t) {
|
---|
1171 | if (p.MinY != 0) {
|
---|
1172 | t -= tmp;
|
---|
1173 | resize = true;
|
---|
1174 | }
|
---|
1175 | } else if (t > 0) {
|
---|
1176 | t = 0;
|
---|
1177 | resize = true;
|
---|
1178 | }
|
---|
1179 | tmp = (float)p.MaxY / ClientSize.Height;
|
---|
1180 | if (tmp > b) {
|
---|
1181 | if (p.MaxY != (ClientSize.Height - 1)) {
|
---|
1182 | b += (1 - tmp);
|
---|
1183 | resize = true;
|
---|
1184 | }
|
---|
1185 | } else if (b < 1) {
|
---|
1186 | b = (float)(ClientSize.Height - 1) / ClientSize.Height;
|
---|
1187 | resize = true;
|
---|
1188 | }
|
---|
1189 | if (resize) {
|
---|
1190 | // ... there is still room left we can use for enlarging the render cube
|
---|
1191 | m_plotBoxScreenRectF = new RectangleF(l, t, r - l, b - t);
|
---|
1192 | p.Reason = RenderReason.RecalcLabels;
|
---|
1193 | p.MaxY = int.MinValue;
|
---|
1194 | p.MaxX = int.MinValue;
|
---|
1195 | p.MinY = int.MaxValue;
|
---|
1196 | p.MinX = int.MaxValue;
|
---|
1197 | }
|
---|
1198 | continue;
|
---|
1199 | }
|
---|
1200 | #endregion
|
---|
1201 | break;
|
---|
1202 | }
|
---|
1203 | iRenderingState3(p);
|
---|
1204 | }
|
---|
1205 |
|
---|
1206 | }
|
---|
1207 | }
|
---|
1208 | protected abstract void iRenderingState1(ILRenderProperties p);
|
---|
1209 | /// <summary>
|
---|
1210 | /// [internal] Configure this panel, to make it ready for output, set "m_ready = true" at end!
|
---|
1211 | /// </summary>
|
---|
1212 | protected virtual void Configure() {
|
---|
1213 | foreach (ILGraph graph in m_graphs) {
|
---|
1214 | graph.Configure();
|
---|
1215 | }
|
---|
1216 | // update clipping view
|
---|
1217 | m_clipplanes[0] = -1.0; m_clipplanes[3] = m_clippingView.Max.X;
|
---|
1218 | m_clipplanes[4] = 1.0; m_clipplanes[7] = -m_clippingView.Min.X;
|
---|
1219 | m_clipplanes[9] = -1.0; m_clipplanes[11] = m_clippingView.Max.Y;
|
---|
1220 | m_clipplanes[13] = 1.0; m_clipplanes[15] = -m_clippingView.Min.Y;
|
---|
1221 | m_clipplanes[18] = -1.0; m_clipplanes[19] = m_clippingView.Max.Z;
|
---|
1222 | m_clipplanes[22] = 1.0; m_clipplanes[23] = -m_clippingView.Min.Z;
|
---|
1223 |
|
---|
1224 | m_ready = true;
|
---|
1225 | }
|
---|
1226 | /// <summary>
|
---|
1227 | /// draw the scene: all axes, graphs, background etc. (device dependant)
|
---|
1228 | /// </summary>
|
---|
1229 | /// <param name="p"></param>
|
---|
1230 | protected abstract void iRenderingState2(ILRenderProperties p);
|
---|
1231 | protected abstract void iRenderingState3(ILRenderProperties p);
|
---|
1232 | protected abstract void UpdateMatrices(float width2D, float height2D, float depth2D);
|
---|
1233 | /// <summary>
|
---|
1234 | /// initialize all device specific classes, first called after the panel has been created
|
---|
1235 | /// </summary>
|
---|
1236 | /// <remarks>derived types should init all devices here</remarks>
|
---|
1237 | protected virtual void Initialize() { }
|
---|
1238 | protected PointF GetXTickLabelLine(out Point start2D, out Point end2D) {
|
---|
1239 | PointF anchor = new PointF(0,0); // TickLabelAlign.left;
|
---|
1240 | ILPoint3Df start = new ILPoint3Df(), end = new ILPoint3Df();
|
---|
1241 | ILTickCollection ticks = m_axes[0].LabeledTicks;
|
---|
1242 | float tickLen = (ticks.Direction == TickDirection.Outside) ?
|
---|
1243 | ticks.TickFraction : 0f;
|
---|
1244 | float padX = ticks.Padding, padY = padX;
|
---|
1245 | switch (m_camera.Quadrant) {
|
---|
1246 | case CameraQuadrant.TopLeftFront:
|
---|
1247 | start.X = m_clippingView.Min.X;
|
---|
1248 | start.Y = m_clippingView.Min.Y - tickLen;
|
---|
1249 | start.Z = m_clippingView.Min.Z;
|
---|
1250 | end.X = m_clippingView.Max.X;
|
---|
1251 | end.Y = start.Y;
|
---|
1252 | end.Z = start.Z;
|
---|
1253 | anchor = new PointF(0,0); //TickLabelAlign.left | TickLabelAlign.top;
|
---|
1254 | padX = -m_camera.SinPhi * padX;
|
---|
1255 | padY = (m_camera.CosPhi - m_camera.SinRho * m_camera.SinPhi) * (padY) + m_camera.SinPhi * ticks.Font.Height / 2;
|
---|
1256 | break;
|
---|
1257 | case CameraQuadrant.TopLeftBack:
|
---|
1258 | start.X = m_clippingView.Min.X;
|
---|
1259 | start.Y = m_clippingView.Max.Y + tickLen;
|
---|
1260 | start.Z = m_clippingView.Min.Z;
|
---|
1261 | end.X = m_clippingView.Max.X;
|
---|
1262 | end.Y = start.Y;
|
---|
1263 | end.Z = start.Z;
|
---|
1264 | anchor = new PointF(1,0); //TickLabelAlign.right | TickLabelAlign.top;
|
---|
1265 | padX *= m_camera.SinPhi;
|
---|
1266 | padY = (-m_camera.CosPhi - m_camera.SinRho * m_camera.SinPhi) * padY + m_camera.SinPhi * ticks.Font.Height / 2;
|
---|
1267 | break;
|
---|
1268 | case CameraQuadrant.TopRightBack:
|
---|
1269 | start.X = m_clippingView.Min.X;
|
---|
1270 | start.Y = m_clippingView.Max.Y + tickLen;
|
---|
1271 | start.Z = m_clippingView.Min.Z;
|
---|
1272 | end.X = m_clippingView.Max.X;
|
---|
1273 | end.Y = start.Y;
|
---|
1274 | end.Z = start.Z;
|
---|
1275 | anchor = new PointF(0,0); //TickLabelAlign.left | TickLabelAlign.top;
|
---|
1276 | padX *= m_camera.SinPhi;
|
---|
1277 | padY = (-m_camera.CosPhi + m_camera.SinRho * m_camera.SinPhi) * padY - m_camera.SinPhi * ticks.Font.Height / 2;
|
---|
1278 | break;
|
---|
1279 | case CameraQuadrant.TopRightFront:
|
---|
1280 | start.X = m_clippingView.Min.X;
|
---|
1281 | start.Y = m_clippingView.Min.Y - tickLen;
|
---|
1282 | start.Z = m_clippingView.Min.Z;
|
---|
1283 | end.X = m_clippingView.Max.X;
|
---|
1284 | end.Y = start.Y;
|
---|
1285 | end.Z = start.Z;
|
---|
1286 | if (m_camera.Is2DView) {
|
---|
1287 | anchor = new PointF(.5f, 0); //TickLabelAlign.center | TickLabelAlign.top;
|
---|
1288 | } else {
|
---|
1289 | anchor = new PointF(1,0); //TickLabelAlign.right | TickLabelAlign.top;
|
---|
1290 | }
|
---|
1291 | padX *= -m_camera.SinPhi;
|
---|
1292 | padY = (m_camera.CosPhi + m_camera.SinRho * m_camera.SinPhi) * padY - m_camera.SinPhi * ticks.Font.Height / 2;
|
---|
1293 | break;
|
---|
1294 | case CameraQuadrant.BottomLeftFront:
|
---|
1295 | start.X = m_clippingView.Min.X;
|
---|
1296 | start.Y = m_clippingView.Max.Y + tickLen;
|
---|
1297 | start.Z = m_clippingView.Min.Z;
|
---|
1298 | end.X = m_clippingView.Max.X;
|
---|
1299 | end.Y = start.Y;
|
---|
1300 | end.Z = start.Z;
|
---|
1301 | anchor = new PointF(1,0); //TickLabelAlign.right | TickLabelAlign.top;
|
---|
1302 | padX *= m_camera.SinPhi;
|
---|
1303 | padY = (m_camera.CosPhi - m_camera.SinRho * m_camera.SinPhi) * padY + m_camera.SinPhi * ticks.Font.Height / 2;
|
---|
1304 | break;
|
---|
1305 | case CameraQuadrant.BottomLeftBack:
|
---|
1306 | start.X = m_clippingView.Min.X;
|
---|
1307 | start.Y = m_clippingView.Min.Y - tickLen;
|
---|
1308 | start.Z = m_clippingView.Min.Z;
|
---|
1309 | end.X = m_clippingView.Max.X;
|
---|
1310 | end.Y = start.Y;
|
---|
1311 | end.Z = start.Z;
|
---|
1312 | anchor = new PointF(0,0); //TickLabelAlign.left | TickLabelAlign.top;
|
---|
1313 | padX *= -m_camera.SinPhi;
|
---|
1314 | padY = (-m_camera.CosPhi - m_camera.SinRho * m_camera.SinPhi) * padY + m_camera.SinPhi * ticks.Font.Height / 2;
|
---|
1315 | break;
|
---|
1316 | case CameraQuadrant.BottomRightBack:
|
---|
1317 | start.X = m_clippingView.Min.X;
|
---|
1318 | start.Y = m_clippingView.Min.Y - tickLen;
|
---|
1319 | start.Z = m_clippingView.Min.Z;
|
---|
1320 | end.X = m_clippingView.Max.X;
|
---|
1321 | end.Y = start.Y;
|
---|
1322 | end.Z = start.Z;
|
---|
1323 | anchor = new PointF(1,0); //TickLabelAlign.right | TickLabelAlign.top;
|
---|
1324 | padX *= -m_camera.SinPhi;
|
---|
1325 | padY = (-m_camera.CosPhi + m_camera.SinRho * m_camera.SinPhi) * padY - m_camera.SinPhi * ticks.Font.Height / 2;
|
---|
1326 | break;
|
---|
1327 | default: // BottomRightFront
|
---|
1328 | start.X = m_clippingView.Min.X;
|
---|
1329 | start.Y = m_clippingView.Max.Y + tickLen;
|
---|
1330 | start.Z = m_clippingView.Min.Z;
|
---|
1331 | end.X = m_clippingView.Max.X;
|
---|
1332 | end.Y = start.Y;
|
---|
1333 | end.Z = start.Z;
|
---|
1334 | anchor = new PointF(0,0); //TickLabelAlign.left | TickLabelAlign.top;
|
---|
1335 | padX *= m_camera.SinPhi;
|
---|
1336 | padY = (m_camera.CosPhi + m_camera.SinRho * m_camera.SinPhi) * padY - m_camera.SinPhi * ticks.Font.Height / 2;
|
---|
1337 | break;
|
---|
1338 | }
|
---|
1339 | World2Screen(start, end, out start2D, out end2D);
|
---|
1340 | // align in screen coords
|
---|
1341 | // int offY = (int)((m_camera.SinRho - (m_camera.SinPhi % Math.PI))
|
---|
1342 | // * m_axes[0].LabeledTicks.Font.Height / 2
|
---|
1343 | // + padY);
|
---|
1344 | // add padding
|
---|
1345 | //System.Diagnostics.Debug.WriteLine(m_camera.Phi);
|
---|
1346 | start2D.Y += (int)padY + 1;
|
---|
1347 | end2D.Y += (int)padY + 1;
|
---|
1348 | start2D.X += (int)(padX + 1);
|
---|
1349 | end2D.X += (int)(padX + 1);
|
---|
1350 | return anchor;
|
---|
1351 | }
|
---|
1352 | protected PointF GetYTickLabelLine(out Point start2D, out Point end2D) {
|
---|
1353 | PointF anchor; // = new PointF(0,0); // TickLabelAlign.left;
|
---|
1354 | ILPoint3Df start = new ILPoint3Df(), end = new ILPoint3Df();
|
---|
1355 | ILTickCollection ticks = m_axes[1].LabeledTicks;
|
---|
1356 | float tickLen = (ticks.Direction == TickDirection.Outside) ?
|
---|
1357 | ticks.TickFraction : 0f;
|
---|
1358 | float padX = ticks.Padding, padY = padX;
|
---|
1359 | if (m_camera.Is2DView) {
|
---|
1360 | start.X = m_clippingView.Min.X - tickLen;
|
---|
1361 | start.Y = m_clippingView.Min.Y;
|
---|
1362 | start.Z = m_clippingView.Min.Z;
|
---|
1363 | end.X = start.X;
|
---|
1364 | end.Y = m_clippingView.Max.Y;
|
---|
1365 | end.Z = start.Z;
|
---|
1366 | anchor = new PointF(1, 0); // TickLabelAlign.right | TickLabelAlign.top;
|
---|
1367 | padX *= -m_camera.CosPhi;
|
---|
1368 | padY = (-m_camera.SinPhi + m_camera.SinRho * m_camera.CosPhi) * padY - m_camera.CosPhi * ticks.Font.Height / 2;
|
---|
1369 | } else {
|
---|
1370 | switch (m_camera.Quadrant) {
|
---|
1371 | case CameraQuadrant.TopLeftFront:
|
---|
1372 | start.X = m_clippingView.Min.X - tickLen;
|
---|
1373 | start.Y = m_clippingView.Min.Y;
|
---|
1374 | start.Z = m_clippingView.Min.Z;
|
---|
1375 | end.X = start.X;
|
---|
1376 | end.Y = m_clippingView.Max.Y;
|
---|
1377 | end.Z = start.Z;
|
---|
1378 | anchor = new PointF(1, 0); // TickLabelAlign.right | TickLabelAlign.top;
|
---|
1379 | padX *= -m_camera.CosPhi;
|
---|
1380 | padY = (-m_camera.SinPhi + m_camera.SinRho * m_camera.CosPhi) * padY - m_camera.CosPhi * ticks.Font.Height / 2;
|
---|
1381 | break;
|
---|
1382 | case CameraQuadrant.TopLeftBack:
|
---|
1383 | start.X = m_clippingView.Min.X - tickLen;
|
---|
1384 | start.Y = m_clippingView.Min.Y;
|
---|
1385 | start.Z = m_clippingView.Min.Z;
|
---|
1386 | end.X = start.X;
|
---|
1387 | end.Y = m_clippingView.Max.Y;
|
---|
1388 | end.Z = start.Z;
|
---|
1389 | anchor = new PointF(0, 0); // TickLabelAlign.left | TickLabelAlign.top;
|
---|
1390 | padX *= -m_camera.CosPhi;
|
---|
1391 | padY = (-m_camera.SinPhi - m_camera.SinRho * m_camera.CosPhi) * padY + m_camera.CosPhi * ticks.Font.Height / 2;
|
---|
1392 | break;
|
---|
1393 | case CameraQuadrant.TopRightBack:
|
---|
1394 | start.X = m_clippingView.Max.X + tickLen;
|
---|
1395 | start.Y = m_clippingView.Min.Y;
|
---|
1396 | start.Z = m_clippingView.Min.Z;
|
---|
1397 | end.X = start.X;
|
---|
1398 | end.Y = m_clippingView.Max.Y;
|
---|
1399 | end.Z = start.Z;
|
---|
1400 | anchor = new PointF(1,0); // TickLabelAlign.right | TickLabelAlign.top;
|
---|
1401 | padX *= m_camera.CosPhi;
|
---|
1402 | padY = (m_camera.SinPhi - m_camera.SinRho * m_camera.CosPhi) * padY + m_camera.CosPhi * ticks.Font.Height / 2;
|
---|
1403 | break;
|
---|
1404 | case CameraQuadrant.TopRightFront:
|
---|
1405 | start.X = m_clippingView.Max.X + tickLen;
|
---|
1406 | start.Y = m_clippingView.Min.Y;
|
---|
1407 | start.Z = m_clippingView.Min.Z;
|
---|
1408 | end.X = start.X;
|
---|
1409 | end.Y = m_clippingView.Max.Y;
|
---|
1410 | end.Z = start.Z;
|
---|
1411 | anchor = new PointF(0,0); // TickLabelAlign.left | TickLabelAlign.top;
|
---|
1412 | padX *= m_camera.CosPhi;
|
---|
1413 | padY = (m_camera.SinPhi + m_camera.SinRho * m_camera.CosPhi) * padY - m_camera.CosPhi * ticks.Font.Height / 2;
|
---|
1414 | break;
|
---|
1415 | case CameraQuadrant.BottomLeftFront:
|
---|
1416 | start.X = m_clippingView.Max.X + tickLen;
|
---|
1417 | start.Y = m_clippingView.Min.Y;
|
---|
1418 | start.Z = m_clippingView.Min.Z;
|
---|
1419 | end.X = start.X;
|
---|
1420 | end.Y = m_clippingView.Max.Y;
|
---|
1421 | end.Z = start.Z;
|
---|
1422 | anchor = new PointF(0,0); // TickLabelAlign.left | TickLabelAlign.top;
|
---|
1423 | padX *= m_camera.CosPhi;
|
---|
1424 | padY = (-m_camera.SinPhi + m_camera.SinRho * m_camera.CosPhi) * padY - m_camera.CosPhi * ticks.Font.Height / 2;
|
---|
1425 | break;
|
---|
1426 | case CameraQuadrant.BottomLeftBack:
|
---|
1427 | start.X = m_clippingView.Max.X + tickLen;
|
---|
1428 | start.Y = m_clippingView.Min.Y;
|
---|
1429 | start.Z = m_clippingView.Min.Z;
|
---|
1430 | end.X = start.X;
|
---|
1431 | end.Y = m_clippingView.Max.Y;
|
---|
1432 | end.Z = start.Z;
|
---|
1433 | anchor = new PointF(1,0); // TickLabelAlign.right | TickLabelAlign.top;
|
---|
1434 | padX *= m_camera.CosPhi;
|
---|
1435 | padY = (-m_camera.SinPhi - m_camera.SinRho * m_camera.CosPhi) * padY + m_camera.CosPhi * ticks.Font.Height / 2;
|
---|
1436 | break;
|
---|
1437 | case CameraQuadrant.BottomRightBack:
|
---|
1438 | start.X = m_clippingView.Min.X - tickLen;
|
---|
1439 | start.Y = m_clippingView.Min.Y;
|
---|
1440 | start.Z = m_clippingView.Min.Z;
|
---|
1441 | end.X = start.X;
|
---|
1442 | end.Y = m_clippingView.Max.Y;
|
---|
1443 | end.Z = start.Z;
|
---|
1444 | anchor = new PointF(0,0); // TickLabelAlign.left | TickLabelAlign.top;
|
---|
1445 | padX *= -m_camera.CosPhi;
|
---|
1446 | padY = (m_camera.SinPhi - m_camera.SinRho * m_camera.CosPhi) * padY + m_camera.CosPhi * ticks.Font.Height / 2;
|
---|
1447 | break;
|
---|
1448 | default: // BottomRightFront
|
---|
1449 | start.X = m_clippingView.Min.X - tickLen;
|
---|
1450 | start.Y = m_clippingView.Min.Y;
|
---|
1451 | start.Z = m_clippingView.Min.Z;
|
---|
1452 | end.X = start.X;
|
---|
1453 | end.Y = m_clippingView.Max.Y;
|
---|
1454 | end.Z = start.Z;
|
---|
1455 | anchor = new PointF(1,0); // TickLabelAlign.right | TickLabelAlign.top;
|
---|
1456 | padX *= -m_camera.CosPhi;
|
---|
1457 | padY = (m_camera.SinPhi + m_camera.SinRho * m_camera.CosPhi) * padY - m_camera.CosPhi * ticks.Font.Height / 2;
|
---|
1458 | break;
|
---|
1459 | }
|
---|
1460 | }
|
---|
1461 | World2Screen(start, end, out start2D, out end2D);
|
---|
1462 | // align in screen coords
|
---|
1463 | //int offY = (int)(Math.Abs(m_camera.CosPhi) * ticks.Font.Height / 2);
|
---|
1464 | //offY -= (int)(Math.Sin(m_camera.Rho) * ticks.Font.Height / 2);
|
---|
1465 | start2D.Y += (int)padY;
|
---|
1466 | end2D.Y += (int)padY;
|
---|
1467 | start2D.X += (int)padX;
|
---|
1468 | end2D.X += (int)padX;
|
---|
1469 | return anchor;
|
---|
1470 | }
|
---|
1471 | protected PointF GetZTickLabelLine(out Point start2D, out Point end2D) {
|
---|
1472 | PointF anchor = new PointF(1, .5f); // TickLabelAlign.vertCenter | TickLabelAlign.right;
|
---|
1473 | ILPoint3Df start = new ILPoint3Df(), end = new ILPoint3Df();
|
---|
1474 | ILTickCollection ticks = m_axes[2].LabeledTicks;
|
---|
1475 | float tickLen = 0;
|
---|
1476 | if (ticks.Direction == TickDirection.Outside)
|
---|
1477 | tickLen = ticks.TickFraction;
|
---|
1478 | start.Z = m_clippingView.Min.Z;
|
---|
1479 | switch (m_camera.Quadrant) {
|
---|
1480 | case CameraQuadrant.TopLeftFront:
|
---|
1481 | start.X = m_clippingView.Min.X - tickLen;
|
---|
1482 | start.Y = m_clippingView.Max.Y + tickLen;
|
---|
1483 | break;
|
---|
1484 | case CameraQuadrant.TopLeftBack:
|
---|
1485 | start.X = m_clippingView.Max.X + tickLen;
|
---|
1486 | start.Y = m_clippingView.Max.Y + tickLen;
|
---|
1487 | break;
|
---|
1488 | case CameraQuadrant.TopRightBack:
|
---|
1489 | start.X = m_clippingView.Max.X + tickLen;
|
---|
1490 | start.Y = m_clippingView.Min.Y - tickLen;
|
---|
1491 | break;
|
---|
1492 | case CameraQuadrant.TopRightFront:
|
---|
1493 | start.X = m_clippingView.Min.X - tickLen;
|
---|
1494 | start.Y = m_clippingView.Min.Y - tickLen;
|
---|
1495 | break;
|
---|
1496 | case CameraQuadrant.BottomLeftFront:
|
---|
1497 | start.X = m_clippingView.Min.X - tickLen;
|
---|
1498 | start.Y = m_clippingView.Max.Y + tickLen;
|
---|
1499 | break;
|
---|
1500 | case CameraQuadrant.BottomLeftBack:
|
---|
1501 | start.X = m_clippingView.Max.X + tickLen;
|
---|
1502 | start.Y = m_clippingView.Max.Y + tickLen;
|
---|
1503 | break;
|
---|
1504 | case CameraQuadrant.BottomRightBack:
|
---|
1505 | start.X = m_clippingView.Max.X + tickLen;
|
---|
1506 | start.Y = m_clippingView.Min.Y - tickLen;
|
---|
1507 | break;
|
---|
1508 | case CameraQuadrant.BottomRightFront:
|
---|
1509 | start.X = m_clippingView.Min.X - tickLen;
|
---|
1510 | start.Y = m_clippingView.Min.Y - tickLen;
|
---|
1511 | break;
|
---|
1512 | default:
|
---|
1513 | break;
|
---|
1514 | }
|
---|
1515 | end = start;
|
---|
1516 | end.Z = m_clippingView.Max.Z;
|
---|
1517 | World2Screen(start, end, out start2D, out end2D);
|
---|
1518 | start2D.X -= (ticks.Padding - 1);
|
---|
1519 | end2D.X -= (ticks.Padding - 1);
|
---|
1520 | return anchor;
|
---|
1521 | }
|
---|
1522 | /// <summary>
|
---|
1523 | /// Get size of projected view cube - after (!) rotation but before projection -> world space
|
---|
1524 | /// includes the bounding box, tightly enclosing the current view limits setting
|
---|
1525 | /// No labels, No ticks included!! Just the data cube with roatation!
|
---|
1526 | /// </summary>
|
---|
1527 | /// <param name="x">out, screen size for X</param>
|
---|
1528 | /// <param name="y">out, screen size for Y</param>
|
---|
1529 | /// <param name="z">out, screen size for Z</param>
|
---|
1530 | protected virtual void GetTransformedSize(out float x, out float y, out float z) {
|
---|
1531 | float xSize = m_clippingView.WidthF; // the unrotated width - without labels size
|
---|
1532 | float ySize = m_clippingView.HeightF; // dito for height
|
---|
1533 | float zSize = m_clippingView.DepthF;
|
---|
1534 | if (m_camera.Rho != 0.0f || m_camera.Phi != 0.0f) { // standard 2D view?
|
---|
1535 | float cosPhi = Math.Abs(m_camera.CosPhi);
|
---|
1536 | float sinPhi = Math.Abs(m_camera.SinPhi);
|
---|
1537 | x = (cosPhi * xSize + sinPhi * ySize); //zSize * Math.Abs(m_camera.SinRho) + (Math.Abs(m_camera.CosRho) *
|
---|
1538 | y = zSize * Math.Abs(m_camera.SinRho)
|
---|
1539 | + (Math.Abs(m_camera.CosRho) * (sinPhi * xSize + cosPhi * ySize));
|
---|
1540 | z = zSize * Math.Abs(m_camera.CosRho)
|
---|
1541 | + (Math.Abs(m_camera.SinRho) * (sinPhi * xSize + cosPhi * ySize));
|
---|
1542 | } else {
|
---|
1543 | x = xSize;
|
---|
1544 | y = ySize;
|
---|
1545 | z = zSize;
|
---|
1546 | }
|
---|
1547 | }
|
---|
1548 |
|
---|
1549 | private void axisLabelVertical2D(ILAxis axis) {
|
---|
1550 | ILLabel label = axis.Label;
|
---|
1551 | ILTickCollection ticks = axis.LabeledTicks;
|
---|
1552 | Size tickSize = ticks.Size, labelSize = label.Size;
|
---|
1553 | label.Orientation = TextOrientation.Vertical;
|
---|
1554 | label.Anchor = new PointF(.5f, 0);
|
---|
1555 | label.m_position.X = ticks.m_lineEnd.X - tickSize.Width - ticks.Padding - label.Padding;
|
---|
1556 | switch (label.Alignment) {
|
---|
1557 | case LabelAlign.Center:
|
---|
1558 | label.m_position.Y = (ticks.m_lineEnd.Y + ticks.m_lineStart.Y) / 2;
|
---|
1559 | break;
|
---|
1560 | case LabelAlign.Upper:
|
---|
1561 | label.m_position.Y = ticks.m_lineEnd.Y + labelSize.Width / 2;
|
---|
1562 | break;
|
---|
1563 | default: // lower
|
---|
1564 | label.m_position.Y = ticks.m_lineStart.Y - labelSize.Width / 2;
|
---|
1565 | break;
|
---|
1566 | }
|
---|
1567 | if (label.m_position.Y < labelSize.Width / 2) {
|
---|
1568 | label.m_position.Y = labelSize.Width / 2;
|
---|
1569 | }
|
---|
1570 | if (label.m_position.Y > ClientSize.Height - 1 - labelSize.Width / 2) {
|
---|
1571 | label.m_position.Y = ClientSize.Height - 1 - labelSize.Width / 2;
|
---|
1572 | }
|
---|
1573 | }
|
---|
1574 | private void positionZAxisLabel(ILAxis axis) {
|
---|
1575 | ILLabel label = axis.Label;
|
---|
1576 | ILTickCollection ticks = axis.LabeledTicks;
|
---|
1577 | Size tickSize = ticks.Size, labelSize = label.Size;
|
---|
1578 | label.Orientation = TextOrientation.Vertical;
|
---|
1579 | label.Anchor = new PointF(.5f, 0);
|
---|
1580 | switch (label.Alignment) {
|
---|
1581 | case LabelAlign.Center:
|
---|
1582 | label.m_position.Y = (ticks.m_lineStart.Y + ticks.m_lineEnd.Y) / 2;
|
---|
1583 | break;
|
---|
1584 | case LabelAlign.Upper:
|
---|
1585 | label.m_position.Y = ticks.m_lineEnd.Y - labelSize.Width / 2;
|
---|
1586 | break;
|
---|
1587 | default: // lower
|
---|
1588 | label.m_position.Y = ticks.m_lineStart.Y + labelSize.Width / 2 ;
|
---|
1589 | break;
|
---|
1590 | }
|
---|
1591 | label.m_position.X = ticks.m_lineStart.X - tickSize.Width - ticks.Padding - label.Padding;
|
---|
1592 | if (label.m_position.Y < labelSize.Width / 2) {
|
---|
1593 | label.m_position.Y = labelSize.Width / 2;
|
---|
1594 | }
|
---|
1595 | if (label.m_position.Y > ClientSize.Height - 1 - labelSize.Width / 2) {
|
---|
1596 | label.m_position.Y = ClientSize.Height - 1 - labelSize.Width / 2;
|
---|
1597 | //label.Orientation = TextOrientation.Horizontal;
|
---|
1598 | //label.m_position.X = label.Padding;
|
---|
1599 | //label.m_position.Y = label.Padding;
|
---|
1600 | }
|
---|
1601 | }
|
---|
1602 | private void axisLabel_BottomRightTopLeft(ILRenderProperties p, ILAxis axis) {
|
---|
1603 | ILLabel label = axis.Label;
|
---|
1604 | ILTickCollection ticks = axis.LabeledTicks;
|
---|
1605 | Size tickSize = ticks.Size, labelSize = label.Size;
|
---|
1606 | label.Anchor = new PointF(.5f, 0);
|
---|
1607 | bool horiz = decideLabelHorizontalOrientation(p, m_camera, axis);
|
---|
1608 | if (horiz) {
|
---|
1609 | #region Horizontal
|
---|
1610 | label.Orientation = TextOrientation.Horizontal;
|
---|
1611 | switch (label.Alignment) {
|
---|
1612 | case LabelAlign.Center:
|
---|
1613 | label.m_position.X = (ticks.m_lineStart.X + ticks.m_lineEnd.X) / 2;
|
---|
1614 | break;
|
---|
1615 | case LabelAlign.Upper:
|
---|
1616 | label.m_position.X = ticks.m_lineEnd.X + labelSize.Width / 2;
|
---|
1617 | break;
|
---|
1618 | default: // lower
|
---|
1619 | label.m_position.X = ticks.m_lineStart.X - labelSize.Width / 2;
|
---|
1620 | break;
|
---|
1621 | }
|
---|
1622 | label.m_position.Y = ticks.m_lineStart.Y + tickSize.Height + ticks.Padding + label.Padding;
|
---|
1623 | if (label.m_position.X < labelSize.Width / 2) {
|
---|
1624 | label.m_position.X = labelSize.Width / 2;
|
---|
1625 | }
|
---|
1626 | #endregion
|
---|
1627 | } else {
|
---|
1628 | #region Vertical
|
---|
1629 | label.Orientation = TextOrientation.Vertical;
|
---|
1630 | switch (label.Alignment) {
|
---|
1631 | case LabelAlign.Center:
|
---|
1632 | label.m_position.Y = (ticks.m_lineStart.Y + ticks.m_lineEnd.Y) / 2;
|
---|
1633 | break;
|
---|
1634 | case LabelAlign.Upper:
|
---|
1635 | label.m_position.Y = ticks.m_lineEnd.Y + labelSize.Width / 2;
|
---|
1636 | break;
|
---|
1637 | default: // lower
|
---|
1638 | label.m_position.Y = ticks.m_lineStart.Y - labelSize.Width / 2;
|
---|
1639 | break;
|
---|
1640 | }
|
---|
1641 | label.m_position.X = ticks.m_lineEnd.X - tickSize.Width - label.Padding - ticks.Padding;
|
---|
1642 | if (label.m_position.Y < labelSize.Width / 2)
|
---|
1643 | label.m_position.Y = labelSize.Width / 2;
|
---|
1644 | if (label.m_position.Y > ClientSize.Height - 1 - labelSize.Width / 2) {
|
---|
1645 | label.m_position.Y = ClientSize.Height - 1 - labelSize.Width / 2;
|
---|
1646 | }
|
---|
1647 | #endregion
|
---|
1648 | }
|
---|
1649 | }
|
---|
1650 | private void axisLabel_BottomLeftTopRight(ILRenderProperties p, ILAxis axis) {
|
---|
1651 | ILLabel label = axis.Label;
|
---|
1652 | ILTickCollection ticks = axis.LabeledTicks;
|
---|
1653 | Size tickSize = ticks.Size, labelSize = label.Size;
|
---|
1654 | bool horiz = decideLabelHorizontalOrientation(p, m_camera, axis);
|
---|
1655 | if (horiz) {
|
---|
1656 | #region Horizontal
|
---|
1657 | label.Orientation = TextOrientation.Horizontal;
|
---|
1658 | label.Anchor = new PointF(0.5f,0);
|
---|
1659 | switch (label.Alignment) {
|
---|
1660 | case LabelAlign.Center:
|
---|
1661 | label.m_position.X = (ticks.m_lineEnd.X + ticks.m_lineStart.X) / 2;
|
---|
1662 | break;
|
---|
1663 | case LabelAlign.Upper:
|
---|
1664 | label.m_position.X = ticks.m_lineEnd.X - label.Size.Width / 2;
|
---|
1665 | break;
|
---|
1666 | default: // lower
|
---|
1667 | label.m_position.X = ticks.m_lineStart.X + label.Size.Width / 2;
|
---|
1668 | break;
|
---|
1669 | }
|
---|
1670 | label.m_position.Y = ticks.m_lineStart.Y + tickSize.Height + ticks.Padding + label.Padding;
|
---|
1671 | if (label.m_position.X > ClientSize.Width - labelSize.Width / 2) {
|
---|
1672 | label.m_position.X = ClientSize.Width - labelSize.Width / 2;
|
---|
1673 | }
|
---|
1674 | #endregion
|
---|
1675 | } else {
|
---|
1676 | #region Vertical
|
---|
1677 | label.Orientation = TextOrientation.Vertical;
|
---|
1678 | label.Anchor = new PointF(0.5f, 1);
|
---|
1679 | switch (label.Alignment) {
|
---|
1680 | case LabelAlign.Center:
|
---|
1681 | label.m_position.Y = (ticks.m_lineEnd.Y + ticks.m_lineStart.Y) / 2;
|
---|
1682 | break;
|
---|
1683 | case LabelAlign.Upper:
|
---|
1684 | label.m_position.Y = ticks.m_lineEnd.Y + labelSize.Width / 2;
|
---|
1685 | break;
|
---|
1686 | default: // lower
|
---|
1687 | label.m_position.Y = ticks.m_lineStart.Y - labelSize.Width / 2;
|
---|
1688 | break;
|
---|
1689 | }
|
---|
1690 | label.m_position.X = ticks.m_lineEnd.X + tickSize.Width + ticks.Padding + label.Padding;
|
---|
1691 | if (label.m_position.Y > ClientSize.Height - 1 - labelSize.Width / 2) {
|
---|
1692 | label.m_position.Y = ClientSize.Height - 1 - labelSize.Width / 2;
|
---|
1693 | }
|
---|
1694 | #endregion
|
---|
1695 | }
|
---|
1696 | }
|
---|
1697 | private void axisLabel_TopRightBottomLeft(ILRenderProperties p, ILAxis axis) {
|
---|
1698 | ILLabel label = axis.Label;
|
---|
1699 | ILTickCollection ticks = axis.LabeledTicks;
|
---|
1700 | Size tickSize = ticks.Size, labelSize = label.Size;
|
---|
1701 | bool horiz = decideLabelHorizontalOrientation(p, m_camera, axis);
|
---|
1702 | label.Anchor = new PointF(.5f, 0);
|
---|
1703 | if (horiz) {
|
---|
1704 | #region Horizontal
|
---|
1705 | label.Orientation = TextOrientation.Horizontal;
|
---|
1706 | switch (label.Alignment) {
|
---|
1707 | case LabelAlign.Center:
|
---|
1708 | label.m_position.X = (ticks.m_lineEnd.X + ticks.m_lineStart.X) / 2;
|
---|
1709 | break;
|
---|
1710 | case LabelAlign.Upper:
|
---|
1711 | label.m_position.X = ticks.m_lineEnd.X + labelSize.Width / 2;
|
---|
1712 | break;
|
---|
1713 | default: // lower
|
---|
1714 | label.m_position.X = ticks.m_lineStart.X - labelSize.Width / 2;
|
---|
1715 | break;
|
---|
1716 | }
|
---|
1717 | label.m_position.Y = ticks.m_lineEnd.Y + tickSize.Height + ticks.Padding + label.Padding;
|
---|
1718 | if (label.m_position.X < labelSize.Width / 2)
|
---|
1719 | label.m_position.X = labelSize.Width / 2;
|
---|
1720 | if (label.m_position.X > ClientSize.Width - labelSize.Width / 2 - 1)
|
---|
1721 | label.m_position.X = ClientSize.Width - labelSize.Width / 2 - 1;
|
---|
1722 | #endregion
|
---|
1723 | } else {
|
---|
1724 | #region Vertical
|
---|
1725 | label.Orientation = TextOrientation.Vertical;
|
---|
1726 | switch (label.Alignment) {
|
---|
1727 | case LabelAlign.Center:
|
---|
1728 | label.m_position.Y = (ticks.m_lineEnd.Y + ticks.m_lineStart.Y) / 2;
|
---|
1729 | break;
|
---|
1730 | case LabelAlign.Upper:
|
---|
1731 | label.m_position.Y = ticks.m_lineEnd.Y - labelSize.Width / 2;
|
---|
1732 | break;
|
---|
1733 | default: // lower
|
---|
1734 | label.m_position.Y = ticks.m_lineStart.Y + labelSize.Width / 2;
|
---|
1735 | break;
|
---|
1736 | }
|
---|
1737 | label.m_position.X = ticks.m_lineStart.X + tickSize.Width + ticks.Padding + label.Padding;
|
---|
1738 | if (label.m_position.Y < labelSize.Width / 2) {
|
---|
1739 | label.m_position.Y = labelSize.Width / 2;
|
---|
1740 | }
|
---|
1741 | if (label.m_position.Y > ClientSize.Height - 1 - labelSize.Width / 2) {
|
---|
1742 | label.m_position.Y = ClientSize.Height - 1 - labelSize.Width / 2;
|
---|
1743 | }
|
---|
1744 | #endregion
|
---|
1745 | }
|
---|
1746 | }
|
---|
1747 | private void axisLabel_TopLeftBottomRight(ILRenderProperties p, ILAxis axis) {
|
---|
1748 | ILLabel label = axis.Label;
|
---|
1749 | ILTickCollection ticks = axis.LabeledTicks;
|
---|
1750 | Size tickSize = ticks.Size, labelSize = label.Size;
|
---|
1751 | bool horiz = decideLabelHorizontalOrientation(p, m_camera, axis);
|
---|
1752 | label.Anchor = new PointF(.5f, 0);
|
---|
1753 | if (horiz) {
|
---|
1754 | #region Horizontal
|
---|
1755 | label.Orientation = TextOrientation.Horizontal;
|
---|
1756 | switch (label.Alignment) {
|
---|
1757 | case LabelAlign.Center:
|
---|
1758 | label.m_position.X = (ticks.m_lineEnd.X + ticks.m_lineStart.X) / 2;
|
---|
1759 | break;
|
---|
1760 | case LabelAlign.Upper:
|
---|
1761 | label.m_position.X = ticks.m_lineEnd.X - labelSize.Width / 2;
|
---|
1762 | break;
|
---|
1763 | default: // lower
|
---|
1764 | label.m_position.X = ticks.m_lineStart.X + labelSize.Width / 2;
|
---|
1765 | break;
|
---|
1766 | }
|
---|
1767 | label.m_position.Y = ticks.m_lineEnd.Y + tickSize.Height + ticks.Padding + label.Padding;
|
---|
1768 | if (label.m_position.X < labelSize.Width / 2) {
|
---|
1769 | label.m_position.X = labelSize.Width / 2;
|
---|
1770 | }
|
---|
1771 | #endregion
|
---|
1772 | } else {
|
---|
1773 | #region Vertical
|
---|
1774 | label.Orientation = TextOrientation.Vertical;
|
---|
1775 | switch (label.Alignment) {
|
---|
1776 | case LabelAlign.Center:
|
---|
1777 | label.m_position.Y = (ticks.m_lineEnd.Y + ticks.m_lineStart.Y) / 2;
|
---|
1778 | break;
|
---|
1779 | case LabelAlign.Upper:
|
---|
1780 | label.m_position.Y = ticks.m_lineEnd.Y - labelSize.Width / 2;
|
---|
1781 | break;
|
---|
1782 | default: // lower
|
---|
1783 | label.m_position.Y = ticks.m_lineStart.Y + labelSize.Width / 2;
|
---|
1784 | break;
|
---|
1785 | }
|
---|
1786 | label.m_position.X = ticks.m_lineStart.X - tickSize.Width - ticks.Padding - label.Padding;
|
---|
1787 | if (label.m_position.Y < labelSize.Width / 2) {
|
---|
1788 | label.m_position.Y = labelSize.Width / 2;
|
---|
1789 | }
|
---|
1790 | if (label.m_position.Y > ClientSize.Height - 1 - labelSize.Width / 2) {
|
---|
1791 | label.m_position.Y = ClientSize.Height - 1 - labelSize.Width / 2;
|
---|
1792 | }
|
---|
1793 | #endregion
|
---|
1794 | }
|
---|
1795 | }
|
---|
1796 |
|
---|
1797 | // return true if the label needs horizontal orientation
|
---|
1798 | private bool decideLabelHorizontalOrientation(ILRenderProperties p, ILCamera m_camera, ILAxis axis) {
|
---|
1799 | if (p.Reason == RenderReason.RecalcLabels) {
|
---|
1800 | return axis.Label.Orientation == TextOrientation.Horizontal;
|
---|
1801 | }
|
---|
1802 | float offX = axis.LabeledTicks.m_lineStart.X - axis.LabeledTicks.m_lineEnd.X;
|
---|
1803 | float offY = axis.LabeledTicks.m_lineStart.Y - axis.LabeledTicks.m_lineEnd.Y;
|
---|
1804 | return offY * offY < offX * offX;
|
---|
1805 | //if (axis.Index == 0) {
|
---|
1806 | // b = (float)((1.0 - m_camera.SinRho * 0.9) * Math.Sin(m_camera.Phi * 2.0f));
|
---|
1807 | //} else if (axis.Index == 1) {
|
---|
1808 |
|
---|
1809 | //}
|
---|
1810 | //return (m_camera.SinRho >= LABELS_VERTICAL_MIN_RHO
|
---|
1811 | // || Math.Sign(Math.Cos(m_camera.Phi * 2.0)) != (axis.Index * 2 - 1));
|
---|
1812 | }
|
---|
1813 | private int GetMargin4OptimalLabelX() {
|
---|
1814 | return 0;
|
---|
1815 | }
|
---|
1816 | private int GetMargin4OptimalLabelY() {
|
---|
1817 | return 0;
|
---|
1818 | }
|
---|
1819 | private Size GetMaxTicLabelSize(Graphics gr) {
|
---|
1820 | Size ret = m_axes.MeasureMaxTickLabelSize(gr);
|
---|
1821 | // add label sizes
|
---|
1822 | int maxHeight = 0;
|
---|
1823 | if (m_axes[0].Label.Visible && !String.IsNullOrEmpty(m_axes[0].Label.Text)) {
|
---|
1824 | maxHeight = m_axes[0].Label.Size.Height;
|
---|
1825 | }
|
---|
1826 | if (m_axes[1].Label.Visible && !String.IsNullOrEmpty(m_axes[1].Label.Text)) {
|
---|
1827 | if (maxHeight < m_axes[1].Label.Size.Height)
|
---|
1828 | maxHeight = m_axes[1].Label.Size.Height;
|
---|
1829 | }
|
---|
1830 | if (m_axes[2].Label.Visible && !String.IsNullOrEmpty(m_axes[2].Label.Text)) {
|
---|
1831 | if (maxHeight < m_axes[2].Label.Size.Height)
|
---|
1832 | maxHeight = m_axes[2].Label.Size.Height;
|
---|
1833 | }
|
---|
1834 | ret = new Size(ret.Width + maxHeight, ret.Height + maxHeight);
|
---|
1835 | return ret;
|
---|
1836 | }
|
---|
1837 |
|
---|
1838 | /// <summary>
|
---|
1839 | /// calculate the real pixels of the plot cube rectangle for drawing into
|
---|
1840 | /// </summary>
|
---|
1841 | /// <param name="xSize"></param>
|
---|
1842 | /// <param name="ySize"></param>
|
---|
1843 | private void updatePlotCubeScreenRect(float xSize, float ySize, Size tickLabelMargins) {
|
---|
1844 | switch (PlotBoxScreenSizeMode) {
|
---|
1845 | //case PlotCubeScreenSizeMode.Maximum: // <- will be done in PlotCubeScreenSizeMode.set()
|
---|
1846 | // m_plotCubeScreenRectF = new RectangleF(0.0f, 0.0f, 1.0f, 1.0f);
|
---|
1847 | // break;
|
---|
1848 | case PlotBoxScreenSizeMode.Optimal:
|
---|
1849 | case PlotBoxScreenSizeMode.StrictOptimal:
|
---|
1850 | float saveX, saveY;
|
---|
1851 | saveX = ((float)tickLabelMargins.Width / ClientSize.Width);
|
---|
1852 | if (saveX < 0) saveX = 0;
|
---|
1853 | if (saveX > 1) saveX = 1;
|
---|
1854 | saveY = ((float)tickLabelMargins.Height / ClientSize.Height);
|
---|
1855 | if (saveY < 0) saveY = 0;
|
---|
1856 | if (saveY > 1) saveY = 1;
|
---|
1857 | m_plotBoxScreenRectF = new RectangleF(saveX, saveY, 1f - (2 * saveX), 1f - (2 * saveY));
|
---|
1858 | break;
|
---|
1859 | default: // manual: use predefined PlotCubeScreenRectF
|
---|
1860 | break;
|
---|
1861 | }
|
---|
1862 | }
|
---|
1863 |
|
---|
1864 | private void updateLabelPositions(ILRenderProperties p) {
|
---|
1865 | positionZAxisLabel(m_axes[2]);
|
---|
1866 | switch (m_camera.Quadrant) {
|
---|
1867 | case CameraQuadrant.TopRightFront:
|
---|
1868 | axisLabel_TopLeftBottomRight(p, m_axes[0]);
|
---|
1869 | // special case: 2D view?
|
---|
1870 | if (m_camera.SinPhi < 1e-5 && m_camera.SinRho < 1e-5) {
|
---|
1871 | axisLabelVertical2D(m_axes[1]);
|
---|
1872 | } else {
|
---|
1873 | axisLabel_BottomLeftTopRight(p, m_axes[1]);
|
---|
1874 | }
|
---|
1875 | break;
|
---|
1876 | case CameraQuadrant.TopRightBack:
|
---|
1877 | axisLabel_TopRightBottomLeft(p, m_axes[0]);
|
---|
1878 | axisLabel_TopLeftBottomRight(p, m_axes[1]);
|
---|
1879 | break;
|
---|
1880 | case CameraQuadrant.TopLeftFront:
|
---|
1881 | axisLabel_BottomLeftTopRight(p, m_axes[0]);
|
---|
1882 | axisLabel_BottomRightTopLeft(p, m_axes[1]);
|
---|
1883 | break;
|
---|
1884 | case CameraQuadrant.TopLeftBack:
|
---|
1885 | axisLabel_BottomRightTopLeft(p, m_axes[0]);
|
---|
1886 | axisLabel_TopRightBottomLeft(p, m_axes[1]);
|
---|
1887 | break;
|
---|
1888 | case CameraQuadrant.BottomLeftFront:
|
---|
1889 | axisLabel_TopLeftBottomRight(p, m_axes[0]);
|
---|
1890 | axisLabel_TopRightBottomLeft(p, m_axes[1]);
|
---|
1891 | break;
|
---|
1892 | case CameraQuadrant.BottomLeftBack:
|
---|
1893 | axisLabel_TopRightBottomLeft(p, m_axes[0]);
|
---|
1894 | axisLabel_BottomRightTopLeft(p, m_axes[1]);
|
---|
1895 | break;
|
---|
1896 | case CameraQuadrant.BottomRightBack:
|
---|
1897 | axisLabel_BottomRightTopLeft(p, m_axes[0]);
|
---|
1898 | axisLabel_BottomLeftTopRight(p, m_axes[1]);
|
---|
1899 | break;
|
---|
1900 | case CameraQuadrant.BottomRightFront:
|
---|
1901 | axisLabel_BottomLeftTopRight(p, m_axes[0]);
|
---|
1902 | axisLabel_TopLeftBottomRight(p, m_axes[1]);
|
---|
1903 | break;
|
---|
1904 | default:
|
---|
1905 | break;
|
---|
1906 | }
|
---|
1907 | }
|
---|
1908 |
|
---|
1909 | private void updateTickLabelLines() {
|
---|
1910 | // determine tick label lines
|
---|
1911 | ILTickCollection ticks = m_axes[2].LabeledTicks;
|
---|
1912 | ticks.m_anchor = GetZTickLabelLine(out ticks.m_lineStart, out ticks.m_lineEnd);
|
---|
1913 | ticks = m_axes[1].LabeledTicks;
|
---|
1914 | ticks.m_anchor = GetYTickLabelLine(out ticks.m_lineStart, out ticks.m_lineEnd);
|
---|
1915 | ticks = m_axes[0].LabeledTicks;
|
---|
1916 | ticks.m_anchor = GetXTickLabelLine(out ticks.m_lineStart, out ticks.m_lineEnd);
|
---|
1917 | }
|
---|
1918 | #endregion
|
---|
1919 |
|
---|
1920 | #region factory member
|
---|
1921 |
|
---|
1922 | /// <summary>
|
---|
1923 | /// create OpenGL panel
|
---|
1924 | /// </summary>
|
---|
1925 | /// <returns>OpenGL panel</returns>
|
---|
1926 | public static ILPanel Create () {
|
---|
1927 | return Create(GraphicDeviceType.OpenGL);
|
---|
1928 | }
|
---|
1929 | /// <summary>
|
---|
1930 | /// create graphic device specific panel
|
---|
1931 | /// </summary>
|
---|
1932 | /// <param name="type">specify GL type. Supported are: OpenGL (recommended) or Direct3D (alpha state)</param>
|
---|
1933 | /// <returns>GL specific panel</returns>
|
---|
1934 | public static ILPanel Create (GraphicDeviceType type) {
|
---|
1935 | ILPanel ret; Type panelType; Assembly assembly;
|
---|
1936 | string myPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
---|
1937 | switch (type) {
|
---|
1938 | case GraphicDeviceType.Direct3D:
|
---|
1939 | //must create DXPanel dynamically ?
|
---|
1940 | // actually not, because DX is split into individual assembly
|
---|
1941 | // but under mono it seems the runtime tries to load the d3d part
|
---|
1942 | // anyway, so we do without a compile time reference.
|
---|
1943 | assembly = Assembly.LoadFile(Path.Combine(myPath,"ILNumerics.DrawingD3D.dll"));
|
---|
1944 | panelType = assembly.GetType("ILNumerics.Drawing.Platform.OpenGL.ILDXPanel");
|
---|
1945 | ret = (ILPanel)panelType.InvokeMember("ILDXPanel",
|
---|
1946 | BindingFlags.DeclaredOnly | BindingFlags.Public
|
---|
1947 | | BindingFlags.NonPublic | BindingFlags.Instance
|
---|
1948 | | BindingFlags.CreateInstance,
|
---|
1949 | null, null, null);
|
---|
1950 | return ret;
|
---|
1951 | default:
|
---|
1952 | // the default is to use OpenGL, which is included into the main assembly (this one)
|
---|
1953 | assembly = Assembly.GetExecutingAssembly();
|
---|
1954 | panelType = assembly.GetType("ILNumerics.Drawing.Platform.OpenGL.ILOGLPanel");
|
---|
1955 | ret = (ILPanel)panelType.InvokeMember("ILOGLPanel",
|
---|
1956 | BindingFlags.DeclaredOnly | BindingFlags.Public
|
---|
1957 | | BindingFlags.NonPublic | BindingFlags.Instance
|
---|
1958 | | BindingFlags.CreateInstance,
|
---|
1959 | null, null, null);
|
---|
1960 | return ret;
|
---|
1961 | }
|
---|
1962 | }
|
---|
1963 |
|
---|
1964 | /// <summary>
|
---|
1965 | /// Create GL dependend graph factory
|
---|
1966 | /// </summary>
|
---|
1967 | /// <returns>ILGraphFactory,will be used for creating all graphs</returns>
|
---|
1968 | /// <remarks>derived types may return GL dependend factory</remarks>
|
---|
1969 | internal abstract IILCreationFactory GetCreationFactory();
|
---|
1970 | #endregion
|
---|
1971 |
|
---|
1972 |
|
---|
1973 | }
|
---|
1974 | }
|
---|