System and method for interactive projection
Abstract
A system for projecting an interactive image onto an object comprises: an infrared sensor; a projector; and a controller operatively connected to the infrared sensor and the projector. The controller is programmed to: transform a content image to conform to a surface of the object by employing a non-affine transform to map a set of points of a polygon encompassing the content image to the surface resulting in a mapped content image; transform a trigger image to conform to the surface of the object by employing the non-affine transform to map a set of points of a polygon encompassing the trigger image to the surface resulting in a mapped trigger image; send a mapped trigger image signal to the projector whereby the projector projects the mapped trigger image onto the surface of the object; receive a data signal from the infrared sensor; generate a trigger signal based on the data signal; and, in response to the trigger signal, send a mapped content image signal to the projector, whereby the projector projects the mapped content image onto the surface of the object. The infrared sensor monitors defined trigger areas for interaction and utilizes depth data related to the location or touch box of the trigger area associated with the trigger area data structure.

Term
9.3 yearsleft in the term
Expires 30 December 2035.
- Priority
- Filed
- Granted
- Today
- Expires
1 claim: 1 independent, 0 dependent
- 1A system for projecting an interactive image onto an object comprising:an infrared sensor;a projector;and a controller operatively connected to the infrared sensor and the projector, the controller programmed to: transform a content image to conform to a surface of the object by employing a non-affine transform to map a set of points of a polygon encompassing the content image to the surface resulting in a mapped content image;transform a trigger image to conform to the surface of the object by employing the non-affine transform to map a set of points of a polygon encompassing the trigger image to the surface resulting in a mapped trigger image;send a mapped trigger image signal to the projector whereby the projector projects the mapped trigger image onto the surface of the object;receive a data signal from the infrared sensor;generate a trigger signal based on the data signal;and, in response to the trigger signal, send a mapped content image signal to the projector, whereby the projector projects the mapped content image onto the surface of the object, wherein the infrared sensor monitors defined trigger areas for interaction and utilizes depth data related to the location or touch box of the trigger area associated with the trigger area data structure.
1,896 paragraphs in 6 sections, as filed
[0001] The disclosure relates to systems and methods for projecting images. In particular, the disclosure relates to a system and method for projection of interactive areas and mapping of the interactive areas onto complex surfaces.
BACKGROUND OF THE INVENTION
[0002] Active product displays are useful in demonstrating advanced features of various products. Prior art systems are typically passive display systems, in that content is presented to a viewer on a screen with little opportunity for feedback. In other prior art systems, a touch screen computer is employed to allow the viewer to select content for review and to provide feedback. However, these systems require extensive custom set-up or are prohibitively expensive. Further, these systems require extensive maintenance due to frequent wear on the touch screen.
[0003] For example, U.S. Patent No. 7,598,942 to Underkoffler, et al. discloses a gestural interface to visually presented elements on a display screen. Multiple cameras capture movement and detect location and orientation and generate output signals to processors connected to a computer. The processors translate the camera outputs into gestural signals which are interpreted as input information. The computer uses the input information to generate commands to control computer fonctions.
[0004] U.S. Patent No. 7,034,807 toMaggioni discloses a system for interaction with a display. The system includes a recording unit for recording a pointer object in the vicinity of the display. A computer is connected to the recording unit and is used to determine a position of the pointer object. The system requires multiple cameras and multiple reflective surfaces.
Date Reçue/Date Received 2021-11-12
[0005] U.S. Patent Publication No. 2Q12/Q2124Y3 to Plagemann, et al. discloses a system for receiving image information and translating it into computer instructions. Image infonnation is received for a single predetermined action space to identify motion. A camera combined with mirrors, prisms, or optic cables is used to gather the image information. However, only one action area is monitored at any given time.
[0006] U.S. Patent Publication No. 2012/0162077 to Sze, et al. discloses an input device used to detect locations and motions of objects in a virtual working area. A camera is directed to a region of interest. A region of interest is illuminated by a “flat” beam of light. An object is placed in the region of interest and illuminated. The camera captures an image of the object and sends it to the processor. The processor processes the image to obtain locations and movements. Based on the movements, the processor produces computer instructions.
[0007] Therefore, there is a need for a system and method for projecting an interactive environment for a display. The system should provide options for the user to actively select the content to view The system should be easy to set up and should be capable of being easily transported to other locales.
Date Reçue/Date Received 2021-11-12
SUMMARY OF THE INVENTION
[0008] The system disclosed projects a “touchable” image on a three-dimensional object which enables user interaction. The touchable image is defined by a trigger area and a content area.
[0010] The system includes an infrared camera and a projector connected to a computer processor. In one embodiment, a content server and content database are also connected to the computer via a network. Content to be projected is stored in the database. During set-up, the system captures a baseline image of a three-dimensional target surface. The system then transforms the content to correct for projector position and for target curvature. During operation, the corrected content image is projected onto the three-dimensional target surface along with similarly transformed image of the trigger area. The infrared camera then monitors the trigger area for a trigger event and reports it to the server when it occurs. A trigger event occurs when an object is placed inside the trigger area for a predetermined period of time. Upon report of a trigger event, the system fetches the additional stored content, transforms it, and projects it onto the target surface. The computer processor uses both affine and a non-affine transforms to translate and “warp” the content image to match the surface of the target object.
[0011] In an alternate embodiment, the system uses facial recognition software to project predefined content associated with a particular recognized user on the surface of the object.
[0012] The action areas can be comprised of a plurality of separately defined actions areas each corresponding to different content. When a user interacts with an action area, the system recognizes the presence of a user and projects the associated content.
Date Reçue/Date Received 2021-11-12
The affine transformations can be described through linear algebra. In linear algebra, linear transformations can be represented by matrices If Tis a linear transformation mapping R to R<sup>! </sup>and x is a column vector with n entries, then T(x) = Ax
[0013] For some m^n matrix A, called the transformation matrix of T, There are alternative expressions of transformation matrices involving row vectors that are preferred by some authors.
[0014] Matrices allow arbitrary linear transformations to be represented in a consistent format, suitable for computation. This also allows transformations to be concatenated easily (by multiplying their matrices).
[0015] Linear transformations are not the only ones that can be represented by matrices. Some transformations that are non-linear on a n-dimensional Euclidean space R, can be represented as linear transformations on the »+l-dimensional space R<sup>-1</sup>. These include both affine transformations (such as translation) and projective transformations. For this reason, 4<sup>y</sup>4 transformation matrices are widely used in 3D computer graphics. These n+1-dimensional transformation matrices are called, depending on their application, affine transformation matrices, projective transformation matrices, or more generally non-linear transformation matrices. With respect to an w-dimensional matrix, an n+1-dimensional matrix can be described as an augmented matrix,
[0016] In the physical sciences, an active transformation is one which actually changes the physical position of a system, and makes sense even in the absence of a coordinate system whereas a passive transformation is a change in the coordinate description of the physical system (change of basis). The distinction between active and passive transformations is important. By default, by transformation, mathematicians usually mean active transformations,
Date Reçue/Date Received 2021-11-12 while physicists could mean either.
[0017] Put differently, a passive transformation refers to description of the same object as viewed from two different coordinate frames.
[0018] If one has a linear transformation T(x) in functional form, it is easy to determine the transformation matrix A by transforming each of the vectors of the standard basis by T, then inserting the result into the columns of a matrix. In other words,
A = [W T(e<sub>2</sub>) ... W] Eq. 1
[0019] For example, the function T(x) = 5x is a linear transformation. Applying the above process (suppose that h = 2 in this case) reveals that
Γ(χ) = 5x = 5Ix = β θ]χ Eq. 2
O J
[0020] It must be noted that the matrix representation of vectors and operators depends on the chosen basis; a similar matrix will result from an alternate basis. Nevertheless, the method to find the components remains the same.
[0021] Mathematically, vector v can be represented in basis vectors, E =
[4¾ ... e<sub>n</sub>]with coordinates [v]<sub>E</sub> = [y<sub>1</sub>v<sub>2</sub> ...v<sub>n</sub>]<sup>r</sup>:
v = + v<sub>2</sub>e<sub>2</sub> + — + v<sub>n</sub>e<sub>n</sub> = £ = E[v]<sub>e</sub> Eq. 3
[0022] Now, express the result of the transformation matrix A upon v, in the given basis:
A(v) = Α(Σ^ι) = %ViA(ëi) = [A^AÇëj) ...A(e<sub>n</sub>)][v]<sub>£</sub> = Eq. 4 '<sup>α</sup>ι,1 <sup>α</sup>2,1 <sup>α</sup>1.2 <sup>α</sup>2,2 <sup>α</sup>ι,η] [Vi] «2,η *2
Eq. 4(cont.) .<sup>α</sup>η,1 °η,2 <sup>a</sup>n,nJ [^η.
[0023] The elements of matrix A are determined for a given basis E by applying
Date Reçue/Date Received 2021-11-12
A to every è) = [00... (y<sub>}</sub> = 1)... 0]\ and observing the response vector Afy = + + + <sup>a</sup>n,j^n = Σ <sup>a</sup>ij This equation defines the elements, a^, of j-th column of the matrix A.
[0024] To represent affine transformations with matrices, we can use homogeneous coordinates. This means representing a 2-vector (x,y) as a 3-vector (x,y, 1 ), and similarly for higher dimensions. Using this system, translation can be expressed with matrix multiplication.
The functional form x' = x + t<sub>x</sub>; y' = y + t<sub>y</sub> becomes:
x y' ίι lût* 0 1 ty 001 .
Eq. 5
[0025] All ordinary linear transformations are included in the set of affine transformations, and can be described as a simplified form of affine transformations. Therefore, any linear transformation can also be represented by a general transformation matrix. The latter is obtained by expanding the corresponding linear transformation matrix by one row and column, filling the extra space with zeros except for the lower-right comer, which must be set to 1. For example, the clockwise rotation matrix from above becomes:
cos 0 sin 00 — sin 0 cos 00 . 0 01.
Eq. 6
[0026] Using transfonnation matrices containing homogeneous coordinates, translations can be seamlessly intermixed with all other types of transformations. The reason is that the real plane is mapped to the w = 1 plane in real projective space, and so translation in real Euclidean space can be represented as a shear in real projective space. Although a translation is a non-linear transformation in a 2-D or 3-D Euclidean space described by Cartesian coordinates, it becomes, in a 3-D or 4-D projective space described by homogeneous coordinates, a simple
Date Reçue/Date Received 2021-11-12 linear transformation (a shear).
[0027] More affine transformations can be obtained by composition of two or more affine transformations. For example, given a translation T with vector (t'<sub>x</sub>, t'y), a rotation R by an angle Θ counter-clockwise, a scaling S with factors (%s<sub>y</sub>)and a translation T of vector ty), the result M of TRST is:
s<sub>x</sub> cos Θ -s<sub>y</sub> sin Θ t<sub>x</sub>s<sub>x</sub> cos Θ - t<sub>y</sub>s<sub>y</sub> sin Θ 4- t'<sub>x</sub> s<sub>x</sub> sin Θ Sy cos Θ t<sub>x</sub>s<sub>x</sub> sin Θ + t<sub>y</sub>s<sub>y</sub> cos Θ + t'<sub>y</sub> .00 1
Eq. 7
[0028] When using affine transformations, the homogeneous component of a coordinate vector (normally called w) will never be altered. One can therefore safely assume that it is always 1 and ignore it. However, this is not true when using perspective projections.
[0029] Another type of transformation, of particular importance to this disclosure, is the perspective projection. Whereas parallel projections are used to project points onto the image plane along parallel lines, the perspective projection projects points onto the image plane along lines that emanate from a single point, called the center of projection. This means that an object has a smaller projection when it is far away from the center of projection and a larger projection when it is closer. This transformation is used to correct for the position of the projector relative to the three-dimensional target object.
[0030] The simplest perspective projection uses the origin as the center of projection, and z = 1 as the image plane. The functional form of this transformation is then x' = x/z; ÿ = y/z. . We can express this in homogeneous coordinates as:
'x<sub>c</sub>' ™C.
0 0' 0100 0010 .0 010.
·Χ· y 2
-WEq. 8
Date Reçue/Date Received 2021-11-12
[0031] After carrying out the matrix multiplication, the homogeneous component will, in general, not be equal to 1. Therefore, to map back into the real plane we must perform the homogeneous divide or perspective divide by dividing each component by uv:
<img file="CA3138907C_D0001.tif" />
[0032] More complicated perspective projections can be composed by combining this one with rotations, scales, translations, and shears to move the image plane and center of projection wherever they are desired.
[0033] Non-affine transformations such as transformation of a two-dimensional surface to a three-dimensional surface can be accomplished, in theory, by treating the threedimensional surface as a distortion or, in other words, a deviation from true rectilinear projection. This type of transformation is used to correct for the complex shape of the threedimensional target object.
[0034] Although distortion can be irregular or follow many patterns, the most commonly encountered distortions are radially symmetric, or approximately so. Radial distortions can usually be classified as either “barrel” distortions or “pincushion” distortions.
[0035] In barrel distortion, image magnification decreases with distance from the optical axis. The apparent effect is that of an image which has been mapped around a sphere (or barrel). Fisheye lenses, which take hemispherical views, utilize this type of distortion as a way to map an infinitely wide object plane into a finite image area. In a zoom lens barrel distortion appears in the middle of the lens's focal length range and is worst at the wide-angle end of the range.
[0036] In pincushion distortion, image magnification increases with the distance from
Date Reçue/Date Received 2021-11-12 the optical axis. The visible effect is that lines that do not go through the center of the image are bowed inwards, towards the center of the image, like a pincushion.
[0037] A mixture of both types, sometimes referred to as “mustache” distortion or complex distortion, is less common but not rare. It starts out as barrel distortion close to the image center and gradually turns into pincushion distortion towards the image periphery, making horizontal lines in the top half of the frame look like a handlebar mustache.
[0038] These distortions are radial distortions. They imply a nonlinear radius mapping from the object to the image. For example, what is seemingly pincushion distortion is simply an exaggerated radius mapping for large radii in comparison with small radii.
Conversely, barrel distortion is simply a diminished radius mapping for large radii in comparison with small radii.
[0039] Radial distortion can be corrected using Brown's distortion model, also known as the Brown-Conrady model. The Brown-Conrady model corrects both for radial distortion and for tangential distortion caused by physical elements in a lens not being perfectly aligned. The latter is also known as decentering distortion.
Xd = + KiT<sup>2</sup> + K2r<sup>4</sup> + ···) + (?2(τ<sup>2</sup> + 2x£) + 2/^^)(1 + P3r<sup>2</sup> + P^r<sup>4</sup> + — ) Eq.
yd = y<sub>u</sub>(l + Kir<sup>2</sup> + K2r<sup>4</sup> + ···) + (Pi(r<sup>2</sup> + 2y^) + 2P2x<sub>u</sub>y<sub>u</sub>)(l + P<sub>3</sub>r<sup>2</sup> + P<sub>4</sub>r<sup>4</sup> + - ) Eq. 11 where:
(x<sub>d</sub>, yd) =distorted image point as projected on image plane using specified lens, (x<sub>u</sub>, yù) - undistorted image point as projected by an ideal pin-hole camera, (x<sub>c</sub>, yc) = distortion center (assumed to be the principal point),
K<sub>n</sub> = n<sup>th</sup>= radial distortion coefficient,
Date Reçue/Date Received 2021-11-12
Pn = n* tangential distortion coefficient,
... =an infinite series.
[0040] in our case, barrel and pincushion distortions are quadratic, meaning they increase as the square of distance from the center. In mustache distortion the quartic (degree 4) term is significant: in the center, the degree 2 barrel distortion is dominant, while at the edge the degree 4 distortion in the pincushion direction dominates. Other distortions are in principle possible - pincushion in center and barrel at the edge, or higher order distortions (degree 6, degree 8) - but do not generally occur in practical cases, and higher order distortions are small relative to the main barrel and pincushion effects.
[0041] Barrel distortion typically will have a negative term for KI whereas pincushion distortion will have a positive value. Moustache distortion will have a nonmonotonic radial geometric series where for some r the sequence will change sign.
[0041a] In another aspect, a system for projecting interactive images on a threedimensional object comprises: a camera capable of providing distance-to-target information; a projector and the camera both positioned adjacent the object, such that the object is positioned within a field of view of the projector; and a computer, connected to the camera and the projector, programmed to carry out a computer implemented method having the steps of: scanning the object within the field of view with the camera; projecting a trigger area on a surface of the object; warping a polygon to match contours of the surface by employing a non-affine transform to map a set of points of the polygon to the surface; associating the polygon with the trigger area; associating a set of content with the polygon; warping the set of content to the polygon; determining a touch event; and, projecting the warped set of content on the surface, wherein the camera monitors defined trigger areas for interaction and
Date Reçue/Date Received 2021-11-12 utilizes depth data related to the location or touch box of the trigger area associated with the trigger area data structure.
[0041b] In another aspect, a method for projecting an interactive image on a threedimensional object comprises the steps of: providing a camera, capable of providing distanceto-target information, and a projector connected to a computer; positioning the camera and the projector adjacent the object, such that the object is positioned within a field of view of the projector; defining positions of a set of trigger areas on a surface of the object; projecting the set of trigger areas on the surface; warping a polygon to match contours of the surface by employing a non-affine transform to map a set of points of the polygon to the surface; associating the polygon with the trigger area; associating a set of content with the polygon; warping the set of content to the polygon; repeating the steps of projecting the set of trigger areas and determining the presence of the touch event until the touch event is detected; projecting the warped set of content on the surface; determining the presence of an end event; repeating the steps of projecting the set of content and determining the presence of an end event until the end event has occurred; and, terminating the projecting, wherein the camera monitors defined trigger areas for interaction and utilizes depth data related to the location or touch box of the trigger area associated with the trigger area data structure.
10a
Date Reçue/Date Received 2021-11-12
[0041c] In another aspect, a system for projecting an interactive image onto an object comprises: an infrared sensor; a projector; a controller operatively connected to the infrared sensor and the projector, the controller programmed to: transform a content image to conform to a surface of the object by employing a non-affine transform to map a set of points of a polygon encompassing the content image to the surface resulting in a mapped content image; transform a trigger image to conform to the surface of the object by employing the non-affine transform to map a set of points of a polygon encompassing the trigger image to the surface resulting in a mapped trigger image; send a mapped trigger image signal to the projector whereby the projector projects the mapped trigger image onto the surface of the object; receive a data signal from the infrared sensor; generate a trigger signal based on the data signal; and, in response to the trigger signal, send a mapped content image signal to the projector, whereby the projector projects the mapped content image onto the surface of the object, wherein the infrared sensor monitors defined trigger areas for interaction and utilizes depth data related to the location or touch box of the trigger area associated with the trigger area data structure.
10b
Date Reçue/Date Received 2021-11-12
BRIEF DESCRIPTION OF DRAWINGS
[0042] Reference will now be made to the following drawings:
[0043] Figure 1 is a system architecture diagram of a preferred embodiment.
[0044] Figure 2A is a schematic of a camera/projection unit of a preferred embodiment.
[0045] Figure 2B is a schematic of a camera/projection unit of a preferred embodiment.
[0046] Figure 3 is a plan view of a display of a preferred embodiment.
[0047] Figure 4 is a plan view of a display of a preferred embodiment.
[0048] Figure 5 is a top view of a display of a preferred embodiment,
[0049] Figure 6 is a plan view of a display of a preferred embodiment.
[0050] Figure 7 is a plan view of a display of a preferred embodiment.
[0051] Figure 8 is a plan view of a display of a preferred embodiment.
[0052] Figure 9 is a plan view of a display of a preferred embodiment.
[0053] Figure 10 is a plan view of a display of a preferred embodiment.
[0054] Figure 11 is a flow chart of a calibration method of a preferred embodiment.
[0055] Figure 12 is a flow chart of a run time process of a preferred embodiment.
[0056] Figure 13 is a flow chart of a run time process for projection mapping of a preferred embodiment.
[0057] Figure 14 is a flow chart of a facial recognition process of a preferred embodiment.
[0058] Figure 15 is a system architecture diagram of a preferred embodiment.
[0059] Figure 16A is an elevation view of a preferred embodiment.
Date Reçue/Date Received 2021-11-12
[0060] Figure 16B is an elevation view of a preferred embodiment.
[0061] Figure 17 is an isometric view of trigger areas of a preferred embodiment.
[0062] Figure 18A is a diagram of a touchable area application in accordance with one embodiment of the disclosure.
[0063] Figure 18B is a diagram of a trigger data structure in accordance with one embodiment of the disclosure.
[0064] Figure 18C is a diagram of a content data structure in accordance with one embodiment of the disclosure.
[0065] Figure 19A is a data flow diagram of a system using trigger areas in accordance with one embodiment of the disclosure.
[0066] Figure 19B is a flow chart for updating a trigger area in accordance with one embodiment of the disclosure.
[0067] Figure 19C is a view of an area of a trigger area in accordance with one embodiment of the disclosure.
[0068] Figure 19D is a view of a volume of a trigger area in accordance with one embodiment of the disclosure.
[0069] Figure 19E is a flow chart for updating content in accordance with one embodiment of the disclosure.
[0070] Figure 19F shows the matrix transformations applied to content in accordance with one embodiment of the disclosure.
[0071] Figure 20A is a data flow diagram of a system using trigger areas in accordance with one embodiment of the disclosure.
[0072] Figure 20B is a flow chart for determining a touch of a trigger area in
Date Reçue/Date Received 2021-11-12 accordance with one embodiment of the disclosure.
[0073] Figure 21A is a view of the application when a first tab is selected in accordance with one embodiment of the disclosure.
[0074] Figure 2 IB is a view of the application when a second tab is selected in accordance with one embodiment of the disclosure.
Date Reçue/Date Received 2021-11-12
DETAILED DESCRIPTION
[0075] In the descriptions that follow, like parts are marked throughout the specification and drawings with the same numerals, respectively. The drawing figures are not necessarily drawn to scale and certain figures may be shown in exaggerated or generalized form in the interest of clarity and conciseness.
[0076] It will be appreciated by those skilled in the art that aspects of the present disclosure may be illustrated and described herein in any of a number of patentable classes or context including any new and useful process, machine, manufacture, or composition of matter, or any new and useful improvement thereof. Therefore, aspects of the present disclosure may be implemented entirely in hardware or combining software and hardware implementation that may all generally be referred to herein as a “circuit,” “module,” “component,” or “system” (including firmware, resident software, micro-code, etc ). Further, aspects of the present disclosure may take the form of a computer program product embodied in one or more computer readable media having computer readable program code embodied thereon.
[0077] Any combination of one or more computer readable media may be utilized. The computer readable media may be a computer readable signal medium or a computer readable storage medium. For example, a computer readable storage medium may be, but not limited to, an electronic, magnetic, optical, electromagnetic, or semiconductor system, apparatus, or device, or any suitable combination of the foregoing. More specific examples of the computer readable storage medium would include, but are not limited to: a portable computer diskette, a hard disk, a random access memory (“RAM”), a read-only memory (“ROM”), an erasable programmable read-only memory (“EPROM” or Flash memory), an appropriate optical fiber with a repeater, a portable compact disc read-only memory' (“CD-ROM”), an optical storage
Date Reçue/Date Received 2021-11-12 device, a magnetic storage device, or any suitable combination of the foregoing. Thus, a computer readable storage medium may be any tangible medium that can contain, or store a program for use by or in connection with an instruction execution system, apparatus, or device.
[0078] Computer program code for carrying out operations for aspects of the present disclosure may be written in any combination of one or more programming languages, markup languages, style sheets and JavaScript libraries, including but not limited to Windows Presentation Foundation (WPF), HTML/CSS, XAML, and JQuery,
[0079] Aspects of the present disclosure are described herein with reference to flowchart illustrations and/or block diagrams of methods, systems and computer program products according to embodiments of the disclosure. It will be understood that each block of the flowchart illustrations and/or block diagrams, and combinations of blocks in the flowchart illustrations and/or block diagrams, can be implemented by computer program instructions. These computer program instructions may be provided to a processor of a computer interconnected with dedicated and special purpose electronic devices, or other dedicated programmable data processing apparatus to produce a machine, such that the instructions, which execute via the processor of the computer or other programmable data processing apparatus, create an integrated machine to implement the functions described in the flowchart and the block diagrams.
[0080] These computer program instructions may also be stored in a computer readable medium that when executed can direct a computer, other programmable data processing apparatus, or other devices to function in a particular manner, such that the instructions when stored in the computer readable medium produce an article of manufacture including instructions which when executed, cause a computer to implement the function/act specified in the flowchart
Date Reçue/Date Received 2021-11-12 and/or block diagram block or blocks. The computer program instructions may also be loaded onto a computer, other programmable instruction execution apparatus, or other devices to cause a series of operational steps to be performed on the computer, other programmable apparatuses or other devices to produce a computer implemented process such that the instructions which execute on the computer or other programmable apparatus provide processes for implementing the functions/acts specified in the flowchart and/or block diagram block or blocks.
[0081] Referring to Figure 1, system 100 includes network 101, content server 102 connected to network 101, and camera/projector unit 104 connected to network 101. Content server 102 is further connected to content database 103 for the storage of multimedia and other relevant data.
[0082] In a preferred embodiment, network 101 is a wide area network such as the internet, but can include other wide area and intranet networks.
[00831 In a preferred embodiment, camera/projector unit 104 downloads content stored in content database 103 from content server 102 and saved to local memory for later projection. In another embodiment, camera/projector unit 104 streams content stored in content database 103 from content server 102 for projection.
[0084] Referring to Figure 2A in one embodiment, camera/projector unit 200 includes enclosure 201, computer/processor 202, projector 203 connected to computer/processor 202, and camera 204 connected to computer/processor 202.
[0085] Referring to Figure 2B in another embodiment, camera/projector unit 205 positions mirror 206 at angle a adjacent to projector 203 to redirect the field of view of projector 203.
[0086] In a preferred embodiment, computer/processor 202 is a laptop computer
Date Reçue/Date Received 2021-11-12 having a suitable processor and memory for storage of content and database, and any other relevant data. In another embodiment, computer/processor 202 is a tablet computer.
[0087] A projection application is stored in the memory of computer/processor 202 for defining and projecting a set of trigger areas with projector 203, detecting a user presence and recognizing the user with camera 204, detecting a selection of the set of trigger areas with camera 204, and projecting content with projector 203, as will be further described below.
[0088] In a preferred embodiment, camera 204 is a 3-D range camera, such as the Kinect camera from Microsoft Corporation. Camera 204 provides image data in the form of streaming video at the rate of 30 frames per second in a standard 640 x 480 VGA. The focal length of the camera is 525 pixels with a field of view of approximately 63°, Camera 204 also provides distance-to-target information from an on-board infrared transmitter/receiver. The focal length of the infrared transmitter/receiver is 580 pixels with a field of view of approximately 58°. The infrared data is provided as a 16 bit number at a refresh rate of200 μ$.
[0089] Referring to Figure 3, display 300 includes camera/projector unit 301 having field of view 302. Camera/ projector unit 301 is connected to arm 304. Arm 304 is attached to and extends from an overhead ceiling. In a preferred embodiment, field of view 302 can range from approximately 45° to 75°. Product 303 is positioned in field of view 302.
[0090] Referring to Figure 4 in another embodiment, display 400 includes camera/projector unit 401 having field of view 403. Camera/projector unit 401 is connected to and supported by stand 402. Stand 402 is removably connected to the floor. Product 404 is positioned in field of view 403,
[0091] Referring to Figure 5, display 500 includes camera/projector unit 501 attached to arm 502 which is attached to base 508. Camera/projector unit 501 projects trigger areas 504
Date Reçue/Date Received 2021-11-12 and 505 onto the surface of product 503. When a user touches the surface of product 503 in trigger areas 504 and 505, camera/projector unit 501 detects the presence of the user in trigger areas 504 and 505 and projects contents 506 and 507, respectively, onto the surface of product 503. In a preferred embodiment, each of contents 506 and 507 is a video. Any type of graphical images may be employed. For example, if a user touches the hood of the car shown in the drawing, an image of a running engine taken from the same perspective as the user may be projected on the hood to simulate a “see through” effect to alert the user to “see” the running engine through the hood.
[0092] Referring to Figure 6 in another embodiment, display 600 includes camera/projector unit 601 having field of view 602 covering product 603, Camera/projector unit 601 projects trigger areas 604,605,606, and 607 onto the surface of product 603. When a user touches the surface of product in trigger areas 604,605,606, and 607, camera/projector unit 601 projects content 615 onto the surface of product 603.
[0093] In one embodiment, if a user touches the surface of product 603 in any of the trigger areas 604,605,606, and 607, camera/projector unit 601 projects a different color/pattem 616 onto product 603, thereby enabling the user to visualize a potential change to the color or pattern of product 603.
[0094] Stand 608 is positioned adjacent to product 603 and is covered by field of view 602. Stand 608 includes placard 609, support 610 attached to placard 609, and base 611 attached to support 610. Base 611 is removably attached to the floor. Camera/projector unit 601 projects trigger areas 612 and 613 onto the surface of placard 609, When a user touches the surface of placard 609 in trigger areas 612 and 613, camera/projector unit 601 projects content 614 onto placard 609, thereby transforming placard 609 into an interactive digital sign. Content
Date Reçue/Date Received 2021-11-12
614 preferably includes information, videos, and/or pictures of product 603. Content 614 is retrieved from the content server or from the local memory of camera/projector unit 601.
[0095] Referring to Figure 7, display 700 includes camera/projector units 701 and
702. Camera/projector unit 701 has field of view 704 covering product 703 including product side 706. Camera/projector unit 702 has field of view 705 covering product 703 including product side 707. Camera/projector unit 701 projects trigger area 708 onto the surface of product side 706, When a user touches the surface of product side 706 in trigger area 708, camera/projector unit 701 projects a video or graphics content onto the surface of product side 706. Camera/projector unit 702 projects trigger area 709 onto the surface of product side 707. When the user touches the surface of product side 707 in trigger area 709, camera/projector unit 702 projects a video or graphics content onto the surface of product side 707.
[0096] Referring to Figure 8 in another embodiment, display 800 includes product 802 positioned in view of camera/projector unit 801. Camera/projector unit 801 detects the position and presence of user 803 on product 802. In one embodiment, an identity of user 803 is determined through a facial recognition process, as will be further described below. Trigger areas 805 and 806 are projected by camera/projector 801 onto the surface of product 802 adjacent to user 803 in response to the presence of user 803.
[0097] In one embodiment, content 804 is automatically projected onto the surface of product 802 in response to the presence and identity of user 803.
[0098] In another embodiment, content 804 is projected onto the surface of product 802 in response to user 803 touching any of trigger areas 805 and 806.
[0099] In another embodiment, camera/projector unit 801 projects a first video as content 804 onto the surface of product 802 based on the detected presence of user 803. When
Date Reçue/Date Received 2021-11-12 user 803 touches any of trigger areas 805 and 806, content 804 changes to a second video and a third video, respectively For example, when camera/projector unit 801 detects the presence of user 803 on product 802, content 804 is an introduction or welcome video. When user 803 touches trigger area 805, content 804 is switched to a graphical brochure. When user 803 touches trigger area 806, content 804 is switched to a product animation. Any type of content may be employed for content 804.
[0100J Referring to Figure 9 in another embodiment, display 900 includes camera/projector 901 and product 902. In this embodiment, projected content 903 includes and sequentially displays the components of product 902 including base layer 904, support layer 905, padding layer 906 and top layer 907. In a preferred embodiment, projected content 903 includes a set of animations which represent a “pealing away” of each layer. For example, in response to a user interacting with a trigger area, top layer 907 is “pealed away” to reveal padding layer 906. Each layer in succession can be projected individually on product 902 thus enabling the user to visualize the different layers of the product. In one embodiment, projected content 903 covers the entirety of product 902. In another embodiment, projected content 903 covers a portion of product 902.
[0101] Referring to Figure 10 in another embodiment, display 1000 includes camera/projector 1001 and product 1002. Product 1002 rests on floor 1004. Content 1003 is projected by camera/projector unit 1001 onto floor 1004 surrounding product 1002. Content 1003 includes animation which gives the appearance that product 1002 is driving through various environments, such as rain, snow, or mud to give the appearance that product 1002 is moving.
[0102] Referring to Figure 11, method 1100 for calibrating camera/projector unit 200
Date Reçue/Date Received 2021-11-12 will be described. At step 1101, a baseline image of a surface is detennined. In this step, the infrared transmitter/receiver of camera 204 captures a baseline image including depth and color data of the surface of a product. In one embodiment, a thin cover, such as a sheet may be employed to cover a highly reflective surface, such as a surface of a car in order to capture an accurate baseline image.
[0103] At step 1102, a position for each of a set of trigger areas for the product is selected. In a preferred embodiment, each trigger area is an ellipse. Other shapes may be employed. At step 1103, the set of trigger areas is projected on the surface. At step 1104, each trigger area is calibrated by placing a three-dimensional object on the trigger area, such as a hemispherically shaped object. Other three-dimensional objects may be employed. In this step, a position of the three-dimensional object relative to the saved baseline image is captured with camera/projector unit 200.
[0104] At step 1105, the captured position of each three-dimensional object is saved in the memory of camera/projector unit 200. At step 1106, a polygon is warped to match the surface, thereby ensuring that the polygon conforms to the surface on which it will be projected. The polygon may correspond to the entire surface or a section of the surface.
[0105] In a preferred embodiment, a non-affine transform is employed to map a set of points of the polygon to the surface. For example, if the polygon is a square in a flat plane and the surface is an angled surface with respect to the projector, then the points of the square are mapped to a quadrilateral that distorts the square image so that when projected on the angled surface, the projected quadrilateral appears as a square on the angled surface. Other transforms, mapping, and distortion techniques may be employed.
[0106] At step 1107, the warped polygon is associated with the trigger area. At step
Date Reçue/Date Received 2021-11-12
1108, a set of content is determined for the polygon. In this step, a file location of the desired set of content is associated with the polygon. The set of content is downloaded and saved to local memory or linked to a stream for the set of content. At step 1109, the set of content is warped to match the warped polygon so that the selection of the trigger area projects the desired content undistorted on the surface.
[0107] Referring to Figure 12 in one embodiment, runtime process 1200 will be described At step 1201, runtime process 1200 begins. At step 1202, a set of trigger areas is projected onto a surface. At step 1203, a touch event is determined, i.e., a determination is made whether a user is in any of the set of trigger areas. In this step, the camera is queried for a user position. The user position is compared to the coordinates of a boundary for the trigger area. If the user position is not within the boundary of the trigger area, then runtime process returns to step 1202. If the user position is within the boundary of the trigger area, then runtime process proceeds to step 1204.
[0108] At step 1204, a polygon with a set of content associated with the trigger area is projected onto the surface. At step 1205, the presence of an end event is determined. An end event is a predetermined time period or another touch event by the user in the set of trigger areas. The predetermined time period is the runtime of the set of content or any desired time period. If an end event has not occurred, then runtime process 1200 returns to step 1204 to continue projecting the polygon and the set of content. If an end event has occurred, then runtime process 1200 proceeds to step 1206.
[0109] At step 1206, whether a terminate command has been received is determined. If a terminate command has not been received, then runtime process 1200 returns to step 1202. If a terminate command has been received, then runtime process 1200 ends at step 1207.
Date Reçue/Date Received 2021-11-12
[0110] Referring to Figure 13 in another embodiment, runtime process 1300 for projection mapping will be described. At step 1301, a scan of an area, such as a room is performed by a camera to detect any surfaces. At step 1302, the scan of a detected surface is mapped to a virtual area. At step 1303, a polygon and a set of content is warped to match the virtual area.
[0111] In a preferred embodiment, a non-affine transform is employed to map a set of points of the polygon and the set of content to the surface. In other embodiments, other transforms, mapping, and distortion techniques may be employed.
[0112] At step 1304, the camera is queried to determine a presence of a user in the area. At step 1305, if a presence is not detected, then runtime process 1300 returns to step 1304, If a presence is detected, then a set of trigger areas are projected onto the surface at step 1306. At step 1307, a facial recognition process begins to recognize an identity of the user, as will be further described below.
[0113] At step 1308, if the identity of the user is recognized then runtime process 1300 proceeds to step 1309. At step 1309, the polygon and a set of content associated with the user is projected onto the surface. At step 1311, the presence of an end event is determined. An end event is a predetermined time period or another touch event by the user in the set of trigger areas. The predetermined time period is the runtime of the content or any desired time period. If an end event has not occurred, then runtime process 1300 returns to step 1309 to continue projecting the polygon and the set of content. If an end event has occurred, then runtime process 1300 proceeds to step 1313.
[0114] If the identity of the user is not recognized in step 1308, then runtime process 1300 proceeds to step 1310. At step 1310, the polygon and a set of predetermined content is
Date Reçue/Date Received 2021-11-12 projected onto the surface.
[0115] At step 1312, the presence of an end event is determined. If an end event has not occurred, then runtime process 1300 returns to step 1310 to continue projecting the polygon and the set of predetermined content. If an end event has occurred, then runtime process 1300 proceeds to step 1313.
[0116] At step 1313, a touch event determination is made as to whether a user is in the set of trigger areas. In this step, the camera is queried for a user position. The user position is compared to the coordinates of a boundary for any of the set of trigger areas. If the position is not within the boundary of any of the set of the trigger areas, then runtime process 1300 returns proceeds to step 1308, If the position is within the boundary of any of the set of trigger areas, then runtime process proceeds to step 1314.
[0117] At step 1314, a polygon with a set of content associated with the trigger area is projected onto the surface. At step 1315, the presence of an end event is determined. If an end event has not occurred, then runtime process 1300 returns to step 1314 to continue projecting the polygon and the set of content. If an end event has occurred, then runtime process 1300 proceeds to step 1316.
[0118] At step 1316, whether a terminate command has been received is determined. If a terminate command has not been received, then runtime process 1300 returns to step 1304. If a terminate command has been received, then mntime process 1300 ends at step 1317.
[0119] Referring to Figure 14, step 1307 will be further described as facial recognition process 1400, Facial recognition process begins at step 1401. At step 1402, a camera is queried to record the locations of facial features including eye location and color, ear location, chin location and hair color. In a preferred embodiment, the query is accommodated by
Date Reçue/Date Received 2021-11-12
Microsoft SKD Rei. 7.1 .LIB file Microsoft.Kinect.Toolkit.FaceTracking. Any type of facial tracking may be employed. In a preferred embodiment, at least 121 different locations are determined. At step 1403, the distances between facial features are measured. At step 1404, a “facial map” is created. The facial map includes a table of the facial features and the distances between them. At step 1405, the facial map is compared to a set of digital images stored in memory. A result of the comparison is output at step 1406. At step 1407, the process ends.
[0120J Referring to Figure 15, in one embodiment, components of interactive projection system 1500 are local computer 1502, camera 1504, and projector 1506. Local computer 1502, camera 1504, and projector 1506 can be separate components positioned individually or all be contained in a single housing. Camera 1504 collects color and depth data within its field of view, constantly monitoring defined trigger areas for interaction. Projector 1506 displays projectable content and trigger areas on any surface within its field of view. Local computer 1502 stores and manipulates camera data, content files, locations of projected content, and locations of trigger areas and projected trigger areas. Local computer 1502 analyzes camera data to determine if interaction with any trigger areas has occurred as will be further described. Local computer 1502 includes a transform function capable of warping content images in order to project the content on three-dimensional surfaces undistorted as will be further described.
[0121] In a preferred embodiment, local computer 1502 contains a processor, a memory for storage of content, a database, and any other relevant data; and a software module including hardware drivers. Minimum requirements for local computer 1502 include an Intel Core 17 processor, at least eight (8) GB of RAM, at least five (5) GB of local memory, a 2 GB graphics processor, Windows operating system 8.1 or higher, and a USB3 connection to camera 1504. An example of a suitable computer is the Latitude E6540 laptop computer available from
Date Reçue/Date Received 2021-11-12
Dell. In a preferred embodiment, hardware drivers include an image capturing program such as Kinect for Windows available from Microsoft.
[0122] Local computer 1502 is connected to camera 1504. Camera 1504 is a 3-D range camera. Camera 1504 includes firmware for movement interpretation and image recognition. Camera 1504 provides image color data in the form of streaming video at the rate of 30 frames per second in a standard 640 X 480 VGA format at 4 bytes/pixel. The focal length of camera 1504 is 525 pixels with a field of view that can range between approximately 45° to 75°. Camera 1504 also provides distance to target information from an on-board infrared transmitter/receiver pair. The focal length of the infrared transmitter/receiver is 580 pixels with a field of view in the range of approximately 45° to 75°, The infrared data is provided as a 16 bit number at a refresh rate of 200 /«. An example of a suitable camera is the Kinect camera available from Microsoft.
[0123] Local computer 1502 is connected to projector 1506 through an HDMI port and cable. Projector 1506 is a PC ready projector having a brightness of 10,000 lumens and a resolution of 1920 X 1200 WUXGA. Projector 1506 has a throw distance in the range of 4 feet to 40 feet with a standard lens. Alternate lenses are available which can dramatically increase the throw distance of projector 1506. Projector 1506 has a field of view angle in the range of 45° to 75° but can be adjusted with different lenses. An example of a suitable projector is the PLWU8100F available from ViviBright.
[0124] Local computer 1502 is connected to microphone 1512 and speaker 1514. Microphone 1512 allow for the reception of audible commands that can be used to trigger the display or playback of images, video, and audio with respect to one or more content areas. Speaker 1514 allows for the playback of the audio channels associated with a video and for the
Date Reçue/Date Received 2021-11-12 playback of audio files that have been associated with a trigger area.
[0125] In an alternate embodiment, components of interactive projection system 1500 further include network 1510, content server 1522, database 1524, and control computer 1520. Content server 1522 is connected to network 1510. Network 1510 connects local computer 1502 to content server 1522. Content server 1522 is further connected to database 1524 for the storage of multimedia and other relevant data. Network 1510 is a wide area netwoik such as the Internet but can include other wide area or intranet networks. Local computer 1502 can download content stored in database 1524 from content server 1522 and save the content to local memory for later projection. Local computer 1502 can also stream content stored in database 1524 from content server 1522 for projection with projector 1506,
[0126] Control computer 1520 is connected to content server 1522 and connected to local computer 1502 through network 1510. Through control computer 1520, a user can manipulate local computer 1502 and set up interactive projection system 1500 from a remote location. Minimum requirements for control computer 1520 include an Intel Core 17 processor, at least eight (8) GB of RAM, at least five (5) GB of local memory, a 2 GB graphics processor, and Windows operating system 8.1 or higher.
[0127] Referring to Figure 16A and coordinate system 1630, the X axis represents horizontal, the Y axis represents vertical, and the Z axis is out of the page. The relative positions of the components within a viewing space 1602 are shown. Viewing space 1602 is a room having a light level sufficient for the projection of projector 1506 to be adequately viewed by a user. The dimensions of viewing space 1602 are those of a typical showroom floor but can vary greatly dependent on the size of the object of the interactive display and the lens of the projector. In general, camera 1504 is positioned to achieve field of view 1604. Field of view 1604 can
Date Reçue/Date Received 2021-11-12 range from 45° - 75°. Camera 1504 is suspended from ceiling 1640 with arm 1606 but can also be attached to a floor stand with equal success. Object 1608 is positioned on floor 1610 within field of view 1604. The locations of any trigger areas must be within field of view 1604.
[0128] In general, projector 1506 is positioned to achieve field of view 1624. Field of view 1624 can range from 45° - 75°. Projector 1506 may be suspended from ceiling 1640 with arm 1616 but can also extend from a floor stand. Object 1608 is positioned on floor 1610 within field of view 1624, The location of any projected content must be within field of view 1604, Projector 1506 and camera 1504 are separated by a distance 1662 along the Xaxis and by distance 1664 along the Y axis.
[0129] Placard 1622 extends from floor 1610 via stand 1628, As shown, content may be displayed on placard 1622 because placard 1622 is positioned within field of view 1624 of projector 1506. In another embodiment, placard 1622 is positioned within field of view 1604 of camera 1504. In another embodiment, placard 1622 is in field of view 1624 of projector 1506 and field of view 1604 of camera 1504 and can display both content areas and trigger areas. In a preferred embodiment, the total height 1636 of the stand and placard is about 3 to 4 feet, the length 1638 of the placard is about 16 inches, and the width 1652 of the placard is about 12 inches. Distance 1650 is the distance between ceiling 1640 and floor 1610 and is about 16 feet in one preferred embodiment.
[0130] Field of view 1624 of projector 1506 is about 72 degrees and includes field of view 1642 and field of view 1644. Field of view 1642 is the field of view for content area 1632 on the surface of object 1608 and is about 7 degrees. Field of view 1644 is the field of view for content area 1634 on placard 1622 and is about 5 degrees. Placard 1622 and object 1608 are within distance 1660 of about 8 feet of each other so that the images projected onto placard 1622
Date Reçue/Date Received 2021-11-12 and onto the object are within field of view 1624 of projector 1506.
[0131] Field of view 1604 of camera 1504 includes field of view 1646 and field of view 1648. Field of view 1646 is the field of view for trigger area 1620 on the surface of object 1608 and is about 4 degrees. Field of view 1648 is the field of view for trigger area 1626 on the surface of object 1608 and is about 3 degrees. Field of view 1604 of camera 1504 is different from field of view 1624 of projector 1506 so that camera 1504 may monitor trigger areas that are outside of field of view 1624 of projector 1506,
[0132] Referring to Figure 16B, camera 1504 is positioned generally over object 1608. The position of camera 1504 on the X axis and Z axis is dictated by the desired positions of trigger areas. In one embodiment, camera 1504 is positioned within a range of 5 to 16 feet along the F axis above object 1608 and within a range of 10 to 20 feet of floor 1610. Trigger areas shown within the field of view of the camera. Trigger area 1620 is positioned on object 1608. Trigger area 1626 is positioned on the surface of object 1608. The system may project an indicator of trigger area 1626 on the surface of object 1608
[0133] The position of projector 1506 on the X and Z axes is dictated by the desired positions of content areas 1632 and 1634. In one embodiment, projector 1506 is positioned within a range of 4 to 40 feet along the Y axis above any surface in which content is desired to be displayed. The ideal distance being dictated by the lens. The surface on which the system displays content should be within the field of view of the projector. In one embodiment, content area 1632 is positioned on the hood portion of object 1608, which in this case is a car. Content area 1634 is positioned on placard 1622,
[0134] Flat surface 1654, shown in Figure 16C, is a hypothetical surface to be targeted at object 1608. Object 1608 includes curved surface 1656, onto which content area
Date Reçue/Date Received 2021-11-12
1632 is projected. Angle 1658 is the difference between flat surface 1654 and curved surface 1656
[0135] The trigger areas are distinct from the content areas but may be linked with each other. In an alternative embodiment where a trigger area is on the headlight of a car, the associated content area may be on the hood of the car so that when the trigger area on the headlight is touched, a video is played on the content area on the hood and the audio associated with the video is played via one or more speakers. Furthermore, instead of a video being played on the hood, the trigger area on the headlight may be linked to an audio recording so that when the trigger area on the headlight is touched, the audio recording (also known as an audio response) is played.
[0136] In additional embodiments, a computer monitoring the trigger areas is also in communication with the car and can control the functions of the car in response to interaction with the trigger areas. This allows for control of the object—the car—in concert with media displayed or projected onto the object. In one embodiment, interaction with a trigger area on the hood of a car causes a video of the engine to be played on the hood and causes the system to start up the engine of the car. When the object is a car, additional features can be controlled in response to interaction with trigger areas, such as: turning on or off headlights and taillights, locking and unlocking doors, opening and closing windows, opening the trunk, and the like.
[0137] Referring to Figure 16C, surface 1654 is a hypothetical flat surface above object 1608 through which an image from the projected passes. The plane of surface 1654 is perpendicular to the direction that the projector is pointing and is tangential to object 1608.
[0138] Referring to Figure 16D, surface 1656 is the surface of object 1608, which is curved and not flat. Images projected onto curved surfaces, such as surface 1656, instead of onto
Date Reçue/Date Received 2021-11-12 flat surfaces, such as hypothetical surface 1654, are adjusted by warping and transforming the image to match the curvature of the surface.
[0139] Referring to Figure 17A, trigger area is described. Trigger areas 1702 and 1704 are predefined 3-dimensional spaces stored in the database. Trigger areas are monitored by the infrared sensors in camera 1504 for interaction with the system by a user. When the infrared sensors detect a user in a trigger area, a predefined action, such as displaying stored content, is carried out by the system.
[0140] A trigger area can be any three-dimensional shape bounded by a series of points which form lines that enclose a volume. Referring to coordinate system 1706, trigger area 1702 is bounded by a set of points including Xi, Y<sub>b</sub> Zi; X2, Yi, Zi; Xi, Y2, Zi; X2, Y2, Zi; and function 1708. Function 1708, in this example, is a hyperbolic function defined by the equation
C « x<sup>2</sup> + y<sup>2</sup> Eq. 12
[0141] Other hyperbolic functions or linear functions may be used to define any set of points, in the X, Y, or Z directions, defining a general shape, so long as the function is closed with respect to the discrete area. Trigger area 1704 is a three-dimensional polygon. The various X, Y, and Z values for each trigger area can vary. The X and Y values range between 2 and 12 inches, preferably around 7 to 8 inches. The Z value can range between 1 and 4 inches, preferably about 2 inches.
[0142] Figure 18A is a diagram of a set of data elements stored in the computer and accessed by a trigger area software program, such as touchable area application 1802, in accordance with one embodiment. Touchable area application 1802 is an application running on a computer system that allows for the display of projected content onto objects and surfaces based user interaction with trigger areas that have been associated with and linked to the
Date Reçue/Date Received 2021-11-12 projected content Touchable area application 1802 includes tabs 1804,1806, and 1808, one or more content controls 1852; and one or more trigger controls 1854.
[0143] Tabs 1804,1806, and 1808 are user interface elements displayed in the application window of touchable area application 1802 that allow for the selection between different modes of the application, such as modes 1910,1912, and 1914 shown in Figure 19A. Tabs 1804,1806, and 1808 are displayed in display area 1816.
[0144] Display area 1816 is the display space of touchable area application 1802. Touchable Area Application includes trigger controls 1854 and content controls 1852 that are displayed in display area 1816.
[0145] Trigger controls 1854 are each associated with an instance of trigger area data structure 1818. Trigger area data structure 1818 include several fields of data to identify a trigger area that is monitored by a camera with the computer, such as camera 1504 and computer 1502 of Figure 15.
[0146] Content controls 1852 are each associated with an instance of content data structure 1820. Content data structure 1820 identifies the content and the content area in which the content is displayed by the system. Content data structure 1820 includes several data fields to identify the content and control its display.
[0147] Figure 18B is a diagram of a trigger area data structure in accordance with one embodiment of the disclosure. Trigger area data structure 1818 is associated with trigger control 1854 and includes coordinates 1822, type 1824, name 1826, identifier 1828, depth data 1830, content data strccture 1820, and filename 1834, The data associated with trigger area data structure 1818 is stored to one or more files that allows trigger data structure area 1818 to be saved and reloaded by touchable area application 1802.
Date Reçue/Date Received 2021-11-12
[0148] Coordinates 1822 identify x and y locations for each of four comers for where trigger control 1852 is displayed in display area 1816.
[0149] Type 1824 identifies a type of content associated directly with trigger area data structure 1818, such as an image or video.
[0150] Name 1826 is a user friendly name that identifies an instance of a trigger control.
[0151] Identifier 1828 is a unique identifier, such as a globally unique identifier (GUID), which is given to each trigger control 1854 of touchable area application 1802 to access trigger control 1854.
[0152] Depth data 1830 identifies the three-dimensional location or touch box associated with trigger area data structure 1818 and trigger control 1854.
[0153] Content data structure 1820 identifies the content area that is associated with trigger area data structure 1818 and trigger control 1854.
[0154] Filename 1834 identifies a file, such as an image file, that provides a default image for trigger control 1854. Filename 1834 may point to a fully transparent image so that, by default, no image is displayed by trigger control 1854.
[0155] Figure 18C is a diagram of a content data structure in accordance with one preferred embodiment. Content data structure 1820 is associated with content control 1852 and includes several data fields to identify and display content within display area 1816 of touchable area application 1802.
[0156] Coordinates 1836 identify x and y locations for each of the comers of content control 1852. The comers identified by coordinates 1836 form a polygon. When the image or video associated with content data structure 1820 is displayed, the comers of the image or video
Date Reçue/Date Received 2021-11-12 are warped and transformed to fit the shape identified by coordinates 1836.
[0157] Type 1838 identifies the type of content associated with content data structure 1820 and content control 1852. Content types include image, video, sound, and the like.
[0158] Loop 1840 identifies how many times to loop the content when, for example, type 1838 of content area 1820 identifies that the content is a video.
[0159] Orientation 1842 identifies the orientation used to display images associated with content control 1852, In one embodiment, Orientation 1842 specifies that, when displayed, the image or video associated with content control 1852 is flipped about the horizontal or vertical axes or rotated by a multiple of 90 degrees.
[0160] Filename 1844 identifies the filename of the image or video associated with content data structure 1820 and content control 1852. In additional embodiments, filename 1844 is a link to static or dynamic content such as a video file, a streaming video file, or a live camera stream that is played in response to interaction with a trigger area.
[0161] Identifier 1846 is a unique identifier or GUID that is given to each content control 1852 of touchable area application 1802 to access content control 1852.
[0162] Name 1848 is a user friendly name that identifies an instance of a content control.
[0163] Figure 19A is a data flow diagram of a system calibrating trigger areas and content areas in accordance with the disclosure. In this embodiment, the system includes computer 1902, camera 1904, projector 1906, and display 1908.
[0164] Computer 1902 is connected to range camera 1904 via a USB (universal serial bus) 3.0 connection and is connected to projector 1906 and display 1908 by an HDMI (highdefinition multimedia interface) connection. Computer 1902 controls the images displayed by
Date Reçue/Date Received 2021-11-12 display 1908 and projector 1906. Camera 1904 provides color data and depth data. Projector 1906 projects images sent from computer 1902 onto any surface in front of projector 1906, including one or more display stands, objects, and screens. Display 1908 displays the application to aid the calibration process.
[0165] The touchable area application uses three modes to perform the calibration process, first mode 1910, second mode 1912, and third mode 1914. When first mode 1910 is selected, user interface controls are associated with the touchable area application. For example, in the case where a static image is displayed by default and two videos are shown based on interaction with two trigger areas, the static image, the two videos, and the two trigger controls are added to the touchable area application. In First mode 1910, the application performs steps 1916,1918,1920, and 1922.
[0166] In second mode 1912, the three-dimensional real world locations for trigger areas are selected. In second mode 1912, the application performs steps 1924,1926,1928,1930, and 1932.
[0167] In third mode 1914, the projected locations of the projected content is selected, fine-tuned, and aligned. In third mode 1914 the application performs steps 1934,1936, 1938, and 1940
[0168] At step 1916, a first tab is selected in the touchable area application to set the mode of the touchable area application to first mode 1910. One example of code for selecting a first tab is shown in the computer program listing appendix in the computer program listing of the file named MainWindow xaml.es at lines 922-926,
[0169] At step 1918, the display image of the application is sent to display 1908 so that the user interface controls—trigger controls and content controls—can be added and
Date Reçue/Date Received 2021-11-12 manipulated.
[0170] At step 1920, trigger controls and content controls are added and updated.
New trigger controls and content controls may be added and the associations between the trigger controls, trigger areas, content controls, and content areas may be updated. The comers of the content controls and trigger controls can be moved or dragged to reshape the images and video that are projected onto the content areas and trigger areas. One example of code that performs this function is shown in the computer program listing appendix in the computer program listing of the file named NonAffineTransformControl.xaml .es at lines 437-476. This code calls a function to determine a transformation matrix, which is shown in the computer program listing appendix in the computer program listing of the file named NonAffineTransformControl xaml cs at lines 1220-1258. One example of code for updating trigger or content controls is shown in the computer program listing appendix in the computer program listing of the file named NonAffineTransformControl.xaml.es at lines 478-512.
[0171] At step 1922, for each change to the user interface controls from step 1920, the image sent to display 1908 is updated. This provides feedback to allow the sequences, timing, and interaction between the trigger controls and content controls.
[0172] At step 1924, a second tab is selected to shift the application to second mode 1912 to allow for the selection of the physical locations of the trigger areas that are associated with trigger controls. One example of code for selecting a second tab is shown in the computer program listing appendix in the computer program listing of the file named MainWindow.xaml.es at lines 927-971.
[0173] At step 1926, computer 1902 receives color and depth data from camera 1904.
[0174] At step 1928, the display area of the application window of the application is
Date Reçue/Date Received 2021-11-12 changed to show a combination of the color and depth data received from camera 1904 with the trigger controls overlaid onto the image.
[0175] At step 1930, the trigger controls that were added in first mode 1910 are associated physical locations that are monitored by camera 1904. The associations are created by dragging and moving the trigger controls displayed on display 1908. One example of code for updating trigger controls is shown in the computer program listing appendix in the computer program listing of the file named NonAffineTransformControl xaml .es at lines 478-512,
[0176] At step 1932, for each change to a trigger control and each change in the color and depth data received from camera 1904, computer 1902 updates the image sent to display 1908
[0177] At step 1934, a third tab, such as third tab 1808 of Figure 18, is selected to set the mode of the application to third mode 1914 to allow for selection of the location of the content areas that will be associated with the content controls. One example of code for selecting a third tab is shown in the computer program listing appendix in the computer program listing of the file named MainWindow.xaml.es at lines 916-920.
[0178] At step 1936, computer 1902 stops displaying the color and depth data from camera 1904 and displays the touchable area application as a full screen window on projector 1906 including the user interface controls. Projector 1906 projects the image from computer 1902 onto the surfaces and objects in front of projector 1906. For example, when camera 1904 projects onto the hood of a car the content displayed by the touchable area application is an image of the engine. In an alternative embodiment, the image sent by computer 1902 to projector 1906 is also sent to display 1908 so that the image is displayed by both display 1908 and by projector 1906.
Date Reçue/Date Received 2021-11-12
[0179] At step 1938, the content control is updated. For example, the sizes of the content control are adjusted to match the surfaces onto which they are being projected. When the hood of the car has a trapezoidal shape, the comers of the content control are dragged to match the trapezoidal shape of the hood. One example of code for updating content controls is shown in the computer program listing appendix in the computer program listing of the file named NonAffineTransformControl.xaml.es at lines 478-512.
[0180] At step 1940, for each update to the content controls from step 1938, the image sent to the projector is updated to include the changes made in step 1938.
[0181] Figure 19B is a flow chart for updating a trigger area associated with a trigger control in accordance with one embodiment of the disclosure. The method for updating a trigger area of Figure 19B is one embodiment for step 1930 of Figure 19A.
[0182] At step 1942, color and depth data are received from a camera, such as camera 1904. The color and depth data are received as one or more byte streams that contain two frames of data, one based on the color sensor of the camera and one based on the infrared depth sensor of the camera. The resolution of the color sensor and the depth sensor differ so that the resolution of the two frames of data also differ. As one example, the color data may have a resolution of 1920 by 1080 with 32 bits of color information per pixel and the depth data may have a resolution of 640 by 480 with 16 bits of depth information per pixel.
[0183] At step 1944, a combination of the color and depth data is displayed. The color data resolution is cropped to the depth data resolution. Within the cropped resolution, color data is displayed if the depth data indicates there is a surface or object within the range of the depth sensor.
[0184] At step 1946, a trigger area associated with a trigger control is selected. The
Date Reçue/Date Received 2021-11-12 trigger area identifies the three-dimensional coordinates of a trigger area that is stored in a trigger area data structure associated with a trigger control and is with respect to the camera that provides the depth data. As shown in Figure 19C, area 1952 is an area of a surface within the range and viewing area of the depth sensor. In a preferred embodiment, the shape of the area defaults to a square or rectangle, but any other shape can be used.
[0185] At step 1948, a depth for the trigger area is selected. The depth combined with the trigger area creates a volume that is associated with a trigger area and is used to determine if the trigger area has been touched. Figure 19D shows volume 1954 created from area 1952 through the addition of depth 1956.
[0186] At step 1950, the trigger area and depth are stored. The trigger area and depth are associated with the trigger area and saved to the database. In a preferred embodiment, the trigger area and depth are stored in depth data 1830 of trigger area data structure 1818 of Figure 18B.
[0187] Figure 19E is a flow chart for updating a content area in accordance with one embodiment of the disclosure. The method for updating a content area of Figure 19E is one embodiment for step 1938 of Figure 19A.
[0188] At step 1958, an initial flat projection area is selected. The native resolution of the content that is selected and associated with a content control provides the initial flat projection area. Figure 19F shows initial flat projection 1968 of content that has been selected.
[0189] At step 1960, an area related to an affine transformation is selected. In a preferred embodiment, the area for the affine transformation is selected by dragging the comers the content area into a desired shape. As an example, when the content area is a rectangular image, one or more of the comers are dragged to form a scaled parallelogram shape, as shown by
Date Reçue/Date Received 2021-11-12 transformation 1970 of Figure 19F.
[0190] At step 1962, an area related to a non-affine transformation is selected. In a preferred embodiment, the area is selected by dragging one or more of the comers and lines that from the boundary of the content area into curved shapes, as shown by transformation 1972 of Figure 19F.
[0191] At step 1964, a brush or filter is created from the affine transformation and the non-affine transformation. The brush will be applied to the content associated with the content control to transform the original size and shape of the content to the selected size and shape of the area selected via steps 1960 and 1962 that correspond to an affine transformation and a nonaffine transformation. When the content is a video, the brush is applied to each frame of the video as the video is displayed.
[0192] At step 1966, the brush created from the selected areas for the affine transformation and the non-affine transformation are saved to persistent storage
[0193] Figure 19F shows the matrix transformations applied to content in accordance with one embodiment of the disclosure. Flat projection 1968 is an initial projection that has not been warped and transformed. Projection 1970 has been warped and transformed using an affine transformation. Projection 1972 has been warped and transformed using a non-affine transformation
[0194] The following code listing provides an example of calculating a transformation:
II The input array of points describes a 2D rectangle
I I (with Z assumed to be zero) in the order // lower-left, upper-left, lower-right, upper-right.
Date Reçue/Date Received 2021-11-12
II The returned transform maps the points (0,0,0),
U (0,1,0), (1,0,0), and (1, 1,0) to these points.
private Matrix3D CalculateNonAffineTransform(Point3D[] points)
H Affine transform //-------------I I This matrix maps (0,0) ~> (xO, y0)
H (0, l)->(xl,yl) // (1,0) —> (x2, y2)
H (1, l)->(x2 + xl+x0,y2 + yl+y0)
Matrix3D A = new Matrix3D();
A.M11 = points[2].X - points[0].X;
A.M12 = points[2].Y - points[0].Y;
A.M21 = points[l].X points[0].X;
A.M22 = points[l].Y - points[0].Y;
A.OffsetX = points[0].X;
A.OffsetY = points[0].Y;
H Calculate point (a, b) that get mapped by the affine
H transform to (x3, y3) double den = A.M11 * A.M22 - A.M12 * A.M21;
double a = (A.M22 * points[3].X - A.M21 * points[3].Y +
A M21 * A.OffsetY A.M22 * A.OffsetX) / den;
Date Reçue/Date Received 2021-11-12 double b = (A.M11 * points[3].Y - A.M12 * points[3] X +
A M12 * AOffsetX - A.M11 * A.OffsetY) / den;
// Non-affine transform //----------------H This matrix maps (0,0) -> (0,0) // (0,1)->(0,1) // (1,0)->(1,0)
H (1, l)->(a, b)
Matrix3D B = new Matrix3DQ;
B.M11 =a/(a + b -1);
B.M22 = b/(a + b -1);
B.M14 = B.M11 -1;
B.M24 = B.M22-1;
return B * A,
[0195] Figure 20A is a data flow diagram of a system using trigger areas in accordance with the disclosure. The system includes computer 2002, range camera 2004, and projector 2006 and has already been calibrated to align the trigger areas and content areas to the surfaces and objects in front of projector 2006.
Date Reçue/Date Received 2021-11-12
[0196] Computer 2002 is connected to range camera 2004 via a USB (universal serial bus) 3.0 connection and is connected to projector 2006 by an HDMI (high-definition multimedia interface) connection. Computer 2002 controls the image displayed by projector 2006 based on data received from range camera 2004. Range camera 2004 provides color data and depth data. Projector 2006 projects images sent from computer 2002 onto any surface in front of projector 2006, including one or more display stands, objects, and screens
[0197] At step 2008, computer 2002 sends the display image that will be received and displayed by projector 2006. The display image has a resolution of, e.g., 1920 by 1080 pixels, which is a native resolution for projector 2006.
[0198] At step 2010, a frame of data is sent from range camera 2004 and received by computer 2002. The color data and the depth data are measured by range camera 2004 and are separated into two different byte streams with different resolutions. The color data is 1920 by 1080 by 32 bits with 8 bits for each of red, green, blue, and alpha channels. The alpha channel defaults to 1. The depth data is 640 by 480 by 16 bits with 13 bits for depth information that measures depth from range camera 2004 in 1 millimeter increments.
[0199] At step 2012, computer 2002 determines if a trigger area has been touched. The determination is made by comparing a base line of the depth data received from range camera 2004 with the current depth data received from range camera 2004. In one preferred embodiment, the baseline depth data is an average of three frames of data captured during the calibration process.
[0200] In one embodiment, detection of a trigger area is determined by calculating whether 20% or more of a volume associated with the trigger area is occupied for at least three frames in a row. One example of code for performing this function is shown in the computer
Date Reçue/Date Received 2021-11-12 program listing appendix in the computer program listing of the file named MainWindow.xaml .es at lines 494-527. The occupation of the volume is determined by the depth associated with the pixels related to the volume of the trigger area. The depth should be less than the baseline depth, but greater than a threshold depth so that a trigger area is only activated by an object that is near the real world location of the trigger area.
[0201] In another embodiment, for each pixel of a trigger area that is occupied, the surrounding eight pixels (forming a 3 by 3 or nine pixel matrix) are tested to see if they are each similarly occupied. This additional precision allows for the touch of a single finger to activate a trigger area.
[0202] At step 2014, computer 2002 updates the display image to be sent to projector 2006 based on frame data received from range camera 2004. When no trigger areas are clicked or activated, the display image is updated for content areas that includes video. When a trigger area is properly activated, the content areas associated with that trigger area are activated.
[0203] At step 2016, computer 2002 sends the updated image. The updated image is based on the content being displayed and the interaction with trigger areas.
[0204] Figure 20B is a flow chart for determining a touch of a trigger area in accordance with one embodiment of the disclosure. One example of code for performing steps analogous to the steps of the flow chart of Figure 20B is shown in the computer program listing appendix in the computer program listing of the file named MainWindow.xaml.es at lines 494527.
[0205] At step 2018, depth data is received from a camera, such as range camera 2004 of Figure 20. In a preferred embodiment, the depth data has a resolution of 640 by 480 pixels with 13 bits of depth information per pixel and aligned to 16 bits.
Date Reçue/Date Received 2021-11-12
[0206] At step 2020, a determination is made as to whether 20% or more of the trigger volume associated with a trigger area has been filled by an object. Each pixel of the depth data related to the trigger volume is compared to its corresponding baseline depth to determine of the pixel includes an object that is a threshold amount above the baseline depth. When 20% or more of the pixels associated with the trigger volume have are determined to include an object, then a frame counter is incremented and the method proceeds to step 2022. Otherwise, the frame counter is decremented to a minimum value of zero and the method returns to step 2018 to wait for the next frame of depth data.
[0207] At step 2022, the frame count for the trigger area is compared. In a preferred embodiment, an object must be detected in relation to the touchable are for three consecutive frame of data. When it has been detected for three consecutive frames of data, the method proceeds to step 2024. Otherwise, the method returns to step 2018 to wait from the next frame of depth data.
[0208] At step 2024, an object of sufficient size has been detected a sufficient number of times to activate a touch event that is associated with the trigger area. In a preferred embodiment the touch event is a mouse click event that is associated with a trigger control associated with the trigger area that causes the display of content via a content control onto the content area. The content displayed in the content area may be static, dynamic, or streamed.
[0209] In Figures 21A and 21B, a system is being calibrated to display content onto an object. A touchable area application, such as touchable area application 1802 of Figure 18, includes tabs 2116,2118, and 2120 that allow for switching between different modes—such as modes 1910,1912, and 1914 of Figure 19A—in the touchable area application for calibration. The first mode to add, associate, and manipulate trigger areas and content areas is accessed by
Date Reçue/Date Received 2021-11-12 selecting tab 2116. The second mode to identify the three-dimensional real world location of the trigger areas associated with trigger controls is accessed by selecting tab 2118. The third mode to display, align, and manipulate the content areas with respect to the object is accessed byselecting tab 2120.
[0210] Figure 21A is a view of the application when a first tab is selected. When first tab 2116 is selected, the application window 2102 is seen on a first display, which is connected to and may be substantially co-located with a computer, such as computer 1902 of Figure 19A. Displaying application window 2102 on the first display allows a user to set up the trigger areas and content areas for the system along with the linking and interaction behaviors associated with the trigger controls, content controls, trigger areas, and content areas. Trigger controls 2104 and 2106 are displayed in application window 2102. Application window 2102 also displays content control 2108, content control 2110, content control 2112 and mouse pointer 2114. Application window 2102 also includes tabs 2116,2118, and 2120. Background 2128 of application window 2102 is black.
[0211] Trigger control 2104 is associated with content control 2110. When the system is running and trigger control 2104 is touched, the content of content control 2110 will be played on top of the content of content control 2108. Similarly, trigger control 2106 is associated with content control 2112 so that touching or clicking trigger control 2106 plays the media or content of content control 2112 on top of the content of content control 2108.
[0212] Content control 2108 includes the default content that is normally displayed by the system. In the embodiment of Figures 21A and 2 IB, content control 2108 is linked to a static image of an engine, such as the engine of car 2122. Content control 2110 is linked to trigger control 2104 and includes a video of the performance characteristics of the object, i.e., car
Date Reçue/Date Received 2021-11-12
2122 of Figures 21B. Content control 2112 is linked to a video of the safety systems of car 2122 and is associated with trigger control 2106.
[0213] Figure 21B is a view of the application when second tab 2118 is selected. When second tab 2118 is selected, instead of showing content controls on background 2128, application window 2102 shows a combination of color and depth data from the camera. When there is no depth data for a pixel, the pixel is shown as black. Otherwise, the RGB (red green blue) color value from the camera is shown. In one embodiment when the resolution of the color data does not match the resolution of the depth data, parts of the image where there is no color data are shown only using the depth data, such as in areas 2130 and 2132. Area 2134 is shown using the combination of color and depth data and areas 2130 and 2132 are shown using only depth data since there is no color data for that portion. Alternative embodiments show any one or combination of color data and depth data on application window 2102.
[0214] Trigger controls 2104 and 2106 can be dragged to any part of the view shown application window 2102 in Figure 21B. When a trigger control is moved, it is associated with the three-dimensional physical location that corresponds with the pixels displayed in application windows 2102 in Figure 21B. A touch box is created for the trigger area associated with the trigger control so that when it is determined that an object sufficiently fills the touch box, the trigger control is activated by creating a virtual mouse click for the trigger control associated with the trigger area in the display area of the touchable area application.
[0215] In an additional embodiment, when the projector can display an image in view of the camera, the projector flashes an image related to the size and location of the trigger area. When the flashing image related to the trigger area is identified from the color data from the camera, the three dimensional coordinates that correspond to the trigger area are identified from
Date Reçue/Date Received 2021-11-12 the depth data and are associated with the trigger control to automatically calibrate the three dimensional location of the trigger area with the trigger control.
[0216] It will be appreciated by those skilled in the art that changes could be made to the embodiments described above without departing from the broad inventive concept. It is understood, therefore, that this disclosure is not limited to the particular embodiments herein, but it is intended to cover modifications within the spirit and scope of the present disclosure as defined by the appended claims.
Date Reçue/Date Received 2021-11-12 using using using using using using using using using using using using using using using using using using using using using using
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
System;
System.Collections.Generic;
System.Configuration;
System.IO;
System.Linq;
System.Runtime.Interopservices,*
System.Text;
System.Threading;
System.Threading.Tasks ;
System.Windows;
System.Windows. Controls;
S ys tem.Wi ndows. Data ;
Systern. Windows. Documents;
System.Windows.Input;
Sys tem. Windows.Medi a;
System.Windows.Media.Imaging;
System.Windows.Media.Media3D;
System.Windows.Navigation;
Sys tem. Windows. Shapes ;
System. Windows. Threading;
System.Xml;
System.Xml.Serialization;
using WpfAnimatedGif;
using Microsoft.Kinect;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace NonAffineTransfcrm { public class WispInteractiveData { public string wispID { get; set; } public int wispindex { get; set; } public int wispPixDepth { get; set; }
J public class WispCoveredFrameltem { //wispID we are working with public string wispID { get; set; } //Captures all the pixels we are worrying about (helps in avg of how many are covered public int totalPixels { get; set; } //for the loop = to count how many of the pixels for this wisp have been covered.
public int currentPixCount { get; set; ) //CountNum - must have at least a certain coverage for a certain number of frames to be considered a click public int frameCcuntNum { get; set; } //after click is achieved, then this is set to true, a new click cannot happen while this is true
Date Reçue/Date Received 2021-11-12
<td> 51.</td><td> //set to false after countNum hits 0 so we can have a new click.</td>
<td> 52.</td><td> public bool isCurrentlylnClickState { get; set; }</td>
<td> 53.</td><td> }</td>
<td> 54.</td><td></td>
<td> 55.</td><td></td>
<td> 56.</td><td></td>
<td> 57.</td><td> public partial· class MainWindow : Window</td>
<td> 58.</td><td> {</td>
<td> 59.</td><td> III <summary></td>
<td> 60.</td><td> III Active Kinect sensor</td>
<td> 61.</td><td> III </summary></td>
<td> 62.</td><td> private KinectSensor kinectSensor = null;</td>
<td> 63.</td><td></td>
<td> 64.</td><td> private const int MapDepthToByte = 8000 / 256;</td>
<td> 65.</td><td></td>
<td> 66.</td><td> HI <summary></td>
<td> 67.</td><td> III Reader for depth frames</td>
<td> 68.</td><td> III </summary></td>
<td> 69.</td><td> III</td>
<td> 70.</td><td> private CoordinateMapper CoordinateMapper = null;</td>
<td> 71.</td><td></td>
<td> 72.</td><td> private MultiSourceFrameReader multiFrameScurceReader =</td>
<td></td><td> null;</td>
<td> 73.</td><td></td>
<td> 74.</td><td> III <surtLiiary></td>
<td> 75.</td><td> III Description of the data contained in the depth frame</td>
<td> 76.</td><td> III </sumnary></td>
<td> 77.</td><td> private FrameDescription depthFrameDescription = null;</td>
<td> 78.</td><td></td>
<td> 79.</td><td> III <summary></td>
<td> 80.</td><td> III Bitmap to display</td>
<td> 81.</td><td> III </summary></td>
<td> 82.</td><td> private WriteableBitmap depthBitmap = null;</td>
<td> 83.</td><td></td>
<td> 84.</td><td> III <summary></td>
<td> 85.</td><td> III Intermediate storage for frame data converted to color</td>
<td> 86.</td><td> III </summary></td>
<td> 87.</td><td> public static byte[] depthpixels = null;</td>
<td> 88.</td><td></td>
<td> 89.</td><td> //displayMe</td>
<td> 90.</td><td> ushort[] _depthData = null;</td>
<td> 91.</td><td> byte[] _colorData = null;</td>
<td> 92.</td><td> byte[] _displayPixels = null;</td>
<td> 93.</td><td> ColorSpacePoint[] _colorPoints = null;</td>
<td> 94.</td><td> readonly int BYTES_PER_PIXEL =</td>
<td></td><td> (PixelFormats.Bgr32.Bits?erPixel + 7)/ 8;</td>
<td> 95.</td><td> WriteableBitmap _bitmap = null;</td>
<td> 96.</td><td></td>
<td> 97.</td><td> int depthwidth = 0;</td>
<td> 98.</td><td> int depthHeight = 0;</td>
<td> 99.</td><td> int colorwidth = 0;</td>
<td> 100.</td><td> int colorHeight = 0;</td>
<td> 101.</td><td></td>
Date Reçue/Date Received 2021-11-12
<td> 102. 103. 104. 105. 106. 107. 108. 109. 110.</td><td> //inverse arrays byte[] InverseDepthPixels = null; III <suroinary> III Current status text to display #region initSpaceeVars” //READ in default settings -these can be changed ir. the app.config file</td>
<td> 111.</td><td> private int ?RAME_NUM_REQUIRED_FOR_CLICK = int. Parse(ConfigurationManager.AppSettings[conf_FRAME_NUM_REQUIRED_ FOR_CLICK]) ;</td>
<td> 112.</td><td> private double WISP_PERCENT_COVERAGE_FOR_CLICK = doable. Parse(ConfigurationManager.AppSettings[oonf_WISP_PERCENT_COV ERAGE_FCR_CLICKJ ) ; // percentage</td>
<td> 113.</td><td> public int MIN_DEPTH_CLICK = int.Parse(ConfigurationManager.AppSettings[conf_MIN_DEPTE_CLICK]) ;</td>
<td> 114.</td><td> public int MAX_DEPTH_CLICK = int.Parse (ConfigurationManager.AppSettings[conf_MAX_DEPTE_CLICK]) ;</td>
<td> 115.</td><td> public int FRAME_SKIP = int.Parse(ConfigurationManager.AppSettings[conf_FRAME_SKIP]) ;</td>
<td> 116. 117. 118.</td><td> public int FRAME_SKIP_CCUNTER = 0; List<WispCoveredFrameltem.> WispViewTabList = new List<WispCoveredFrameItem>();</td>
<td> 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129.</td><td> public bool PauseTouch = false; public int PauseTouchCounter = 0; public int PauseOnLongWaitCounter = 0; public int PauseOnLongWaitMax = 1500; public static bool enterTab2 = false; public static bool enterViewerMode = false; public static string popupRecieve WispName = public static Li$t<Point> recievePop_tempPoints = new List<Point>();</td>
<td> 130. 131. 132.</td><td> public static bool processPopup = false; private List<WispInteractiveData> wispDepths = new List<WispInteractiveData>();</td>
<td> 133. 134. 135. 136.</td><td> public static int theBitMapSourceWidth; //public bool startlnViewMode = false; private string _WispCoveredFrameItem_XMLFile = ’’WispCoveredFrameltem.xml;</td>
<td> 137. 138. 139. 140. 141. 142. 143.</td><td> private string _WispDepths_XMLFile = WispDepths.xml; #endregion public MainWindow() AppDomain currentDomain = AppDorcain.CurrentDomain;</td>
Date Reçue/Date Received 2021-11-12
<td> 144.</td><td> currentDomain.UnhandledException += new UnhandledExceptionEventHandler(KillProgram);</td>
<td> 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 16Û. 161. 162. 163. 164.</td><td> //start 3d Camera startKinect(); Initializecomponent() ; //load in all possible touch points from the xml file LoadWispDepthsFromXML () ; LoadWispsFromXML(); //check if monoter system issues this program a command var sivm - App.startlnViewMode; if (sivm == true) { //load viewer and full screen. //System.Windows.MessageBox. Show (true) ; startAppinFullView() ; ) ) static void KillProgram(object sender, UnhandledExceptionEventArgs args)</td>
<td> 165. 166. 167. 168. 169. 170.</td><td> { Environment.Exit(0); //Exception e = (Exception)args.Exceptionobject; //Console.WriteLine(MyHandler caught : + e.Message); //Console.WriteLine(Runtime terminating: {0}, args.IsTerminating);</td>
<td> 171. 172. 173. 174. 175. 176. 177, 178. 179. 180. 181.</td><td> } public void startKinect() // get the kinectSensor object this.kinectSensor = KinectSensor.GetDefault(); II open the reader for the depth frames this.multiFrameSourceReader = this.kinectSensor.CpenMultiSourceFrameReader(FrameSourceTypes.Depth 1 FrameSourceTypes.Color);</td>
<td> 182. 183. 184.</td><td> this.multiFrameSourceReader.MultiSourceFrameArrived += this.Reader_MultiSourceFrameArrived;</td>
<td> 185. 186.</td><td> this.coordinateMapper = this.kinectSensor.CoordinateMapper;</td>
<td> 187. 188. 189.</td><td> // get FrameDescription from DepthFrameSource this.depthFrameDescription = this.kinectSensor.DepthFrameSource.FrameDescription;</td>
Date Reçue/Date Received 2021-11-12
<td> 190. 191. 192. 193.</td><td> depthwidth = depthFrameDescription.Width; depthHeight = depthFrameDescription.Height; // allocate space to put the pixels being received and converted</td>
<td> 194.</td><td> depthpixels = new byte[this.depthFrameDescription.Width * this.depthFrameDescription.Height];</td>
<td> 195. 196.</td><td> FrameDescription colorFrameDescription = this.kinectSensor.ColorFrameSource.FrameDescription;</td>
<td> 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207.</td><td> colorWidth = colorFrameDescription.Width; colorHeight = colorFrameDescription.Height; //displayMe if (_displayPixels == null) { _depthData = new ushort[depthwidth * depthHeight]; _colorData = new byte[colorwidth * colorHeight * BYTES_PER_PIXEL]7</td>
<td> 208 .</td><td> _displayPixels = new byte[depthwidth * depthHeight * BYTES_PER_PIXEL];</td>
<td> 209.</td><td> _colorPoints = new ColorSpacePoint[depthwidth * depthHeight];</td>
<td> 210. 211.</td><td> ) _bitmap = new WriteableBitmap(depthwidth, depthHeight, 96.0, 96.0, PixelFormats.Bgra32, null);</td>
<td> 212. 213. 214. 215. 216. 217. 218. 219.</td><td> //inverses InverseDepthPixels = new byte[depthwidth * depthHeight]; // create the bitmap to display this.depthBitmap = new WriteableBitmap(this.depthFrameDescription.Width, this.depthFrameDescription.Height, 96.0, 96.0, PixelFormats.Gray8, null);</td>
<td> 220. 221. 222. 223. 224. 225. 226. 227.</td><td> // open the sensor this.kinectSensor.Open (); } //for each frame I can read - do this private void Reader_MultiSourceFrameArrived(object sender, MultiSourceFrameArrivedEventArgs e)</td>
228 .
22$.
230.
231.
232.
Date Reçue/Date Received 2021-11-12
<td> 233. 234. 235. 236. 237. 238 .</td><td> bool depthFrameProcessed = false; DepthFrame df = null; ColorFrame cf = null; bool isBitmapLocked = false; MultiSourceFrame multiSourceFrame = e.FrameReference.AcquireFrame();</td>
<td> 239. 240. 241. 242. 243. 244. 245. 246. 247. 248 . 249. 250. 251. 252. 253. 254. 255. 256. 257.</td><td> if (PauseTouch == true) { PauseTouchCounter++; if (PauseTouchCounter > 60) PauseTouch <sup>_</sup> false; } else ( PauseOnLongWaitCounter++; if (PauseOnLongKaitCounter > PauseOnLongWaitMax) { PauseTouch = true; PauseOnLongKaitCounter = 0; } II txtDebug.Text = Entered Reader; // If the Frame has expired by the time we process this event, return.</td>
<td> 258 . 259. 260. 261. 262. 263.</td><td> if (multiSourceFrame == null) { return; } II We use a try/finally to ensure that we clean up before we exit the function.</td>
<td> 264.</td><td> Π This includes calling Dispose on any Frame objects that we may have and unlocking the bitmap back buffer.</td>
<td> 265. 266. 267.</td><td> try { df = multiSourceFrame.DepthFrameReference.AcquireFrame();</td>
<td> 268 .</td><td> cf = multiSourceFrame.ColorFrameReference.AcquireFrame() ;</td>
<td> 269. 270. 271. 272. 273. 274. 275.</td><td> if (FRAME_SKIP_COUNTER > FRAME_SKIP) { FRAME_SKIP_COUNTER = 0; Il II If any frame has expired by the time we process this event, return.</td>
<td> 276.</td><td> Π II The finally statement will Dispose any that are not null.</td>
<td> 277. 278 .</td><td> if ((df == null) || (cf == null)) {</td>
Date Reçue/Date Received 2021-11-12
<td> 279.</td><td> return;</td>
<td> 280.</td><td> }</td>
<td> 281.</td><td></td>
<td> 282.</td><td> if (enterTab2 == true)</td>
<td> 283.</td><td> {</td>
<td> 284.</td><td> //Inverse Streams</td>
<td> 285.</td><td> H depth stream</td>
<td> 286.</td><td></td>
<td> 287.</td><td></td>
<td> 288 .</td><td> //displayMe</td>
<td> 289.</td><td> if (((depthwidth * depthHeight) ==</td>
<td></td><td> _depthData.Length) && ((colorWidth * colorHeight * BYTES_PER_PIXEL)</td>
<td></td><td> == _colcrData.Length))</td>
<td> 290.</td><td> {</td>
<td> 291.</td><td> df.CopyFrameDataToArray(_depthData);</td>
<td> 292.</td><td></td>
<td> 293.</td><td> if (cf.RawColorlmageFormat ==</td>
<td></td><td> ColorlmageFormat.Bgra)</td>
<td> 294.</td><td> {</td>
<td> 295.</td><td></td>
<td></td><td> cf.CopyRawFrameDataToArray( colorData);</td>
<td> 296.</td><td> “}</td>
<td> 297.</td><td> else</td>
<td> 298 .</td><td> {</td>
<td> 299.</td><td></td>
<td></td><td> cf.CopyConvertedFrameDataToArray(_colorData, ColorlmageFormat.Bgra);</td>
<td> 300.</td><td> )</td>
<td> 301.</td><td></td>
<td> 302.</td><td></td>
<td> 303.</td><td></td>
<td> 304.</td><td></td>
<td></td><td> this.cocrdinateMapper.MapDepthFrameToColorSpace(_depthData,</td>
<td></td><td> _colorPcints);</td>
<td> 305.</td><td></td>
<td> 306.</td><td> Array.Clear(_displayPixels, 0,</td>
<td></td><td> displaypixels.Length);</td>
<td> 307.</td><td></td>
<td> 308 .</td><td> for (int y = 0; y < depthHeight; ++y)</td>
<td> 309.</td><td> {</td>
<td> 310.</td><td> for (int x = 0; x < depthwidth; ++x)</td>
<td> 311.</td><td> {</td>
<td> 312.</td><td> int depthindex = (y *</td>
<td></td><td> depthwidth) + x;</td>
<td> 313.</td><td></td>
<td> 314.</td><td></td>
<td> 315.</td><td> ColorSpacePoint colorPoint =</td>
<td></td><td> _colorPcints[depthindex];</td>
<td> 316.</td><td></td>
<td> 317.</td><td> int colorX =</td>
<td></td><td> (int)Math.Floor(colorPoint.X + 0.5);</td>
<td> 318.</td><td> int colorY =</td>
<td></td><td> (int)Math.Floor(colorPoint.Y + 0.5);</td>
<td> 319.</td><td></td>
Date Reçue/Date Received 2021-11-12
<td> 320.</td><td> if ((colorX >= 0) && (colcrX < colorWidth) && (colorY >= 0; &S (colorY < colorHeight))</td>
<td> 321. 322.</td><td> { int colorindex = ((colorY * colorWidth) + colorX) * BYTES_PER_PIXEL;</td>
<td> 323.</td><td> int displayindex = depthindex * BYTES_PER_PIXEL;</td>
<td> 324. 325.</td><td> _displayPixels[displayindex + 0] = _colorData[colorindex];</td>
<td> 326.</td><td> _displayPixels[displayindex + 1] = _colorData[colorindex + 1];</td>
<td> 327.</td><td> _displayPixels[displayindex + 2] = _colorData[colorindex + 2];</td>
<td> 328 .</td><td> _displayPixels[displayindex + 3] = Oxff;</td>
<td> 329. 330. 331. 332. 333. 334. 335. 336. 337. 338 . 339. 340. 341. 342. 343. 344.</td><td> } } } } } using (DepthFrame depthFrame = df) { if (depthFrame != null) { ! ! the fastest way to process the body index data is to directly access</td>
<td> 345. 346.</td><td> // the underlying buffer using (Microsoft.Kinect.KinectBuffer depthBuffer = depthFrame.LocklmageBuffer ())</td>
<td> 347. 348 .</td><td> { 11 verify data and write the color data to the display bitmap</td>
<td> 349.</td><td> if (((this.depthFrameEescription.Width * this.depthFrameDescription.Height) == (depthBuffer.Size / this.depthFrameDescription.BytesPerPixel)) &&</td>
<td> 350.</td><td> (this.depthFrameDescription.Width == this.depthBitmap.Pixelwidth) && (this.depthFrameDescription.Height == this.depthBitmap.PixelHeight))</td>
<td> 351. 352.</td><td> { II Note: In order to see the full range of depth (including the less reliable far field depth)</td>
<td> 353.</td><td> II we are setting maxDepth to the extreme potential depth threshold</td>
<td> 354.</td><td> ushort maxDepth = ushort.MaxValue;</td>
355.
Date Reçue/Date Received 2021-11-12
356. II If you wish to filter by reliable depth distance, uncomment the following line;
357. Illi maxDepth = depthPrama.DepthMaxReliableDistanca
358 .
359.
360.
361.
362.
363.
364.
365.
366.
367.
368 .
369.
370.
371.
372.
373.
374.
375.
376.
377.
378 .
379.
380.
381.
382.
383 .
this.PrccessDepthFrameData(depthBuffer.UnderlyingBuffer, depthBuffer.Size, depthFrame.DepthMinReliableDistance, maxDepth);
depthFrameProcessed = true;
} } } ) //Inverse Depth Array to match Picture for (int y = 0; y < depthHeight; ++y) { int counter = depthwidth - 1;
for (int x = 0; x < depthwidth; x++) { int depthindex = (y * depthwidth; + x; int reverseindex = (y * depthwidth) + counter;
InverseDepthPixels[depthindex] = depthPixels[reverseindex];
counter—;
} }
depthPixels = InverseDepthPixels;
InverseDepthPixels = new byte[depthwidth * depthHeight];
384.
385.
386. // var r = wispDepths;
387. if (processPopup == true)
388 . {
389.
390. //Remove the wisp if it exists before adding it back, (so when you move around, it doesn't ahve 1000 copies just one)
391. wispDepths.RemoveAll(c => c.wispID == popupRecieve_WispName);
392. WispViewTabList.RemoveAll(c => c.wispID == popupRecieve_WispName);
393.
394. II&AA all points from the clicked wisp to the list.
395. fcreach (Point pt in recievePop_tempPoints)
396. {
397.
Date Reçue/Date Received 2021-11-12
<td> 398 .</td><td> int pixellndex = (int)(pt.X + ((int)pt.Y * this.depthBitmap.PixelWidth)) ;</td>
<td> 399. 400. 401. 402. 403. 404. 405. 406. 407. 408 . 409.</td><td> int depth = 0; if (depthpixels[pixellndex] > 0) depth = depthpixels[pixellndex]; else depth = 0; WispInteractiveData wid = new WispInteractiveData();</td>
<td> 410. 411. 412. 413. 414. 415. 416. 417. 418. 419.</td><td> wid.wispID = popupRecieve_WispName; wid.wispindex = pixellndex; wid.wispPixDepth = depth; wispDepths.Add(wid); } //Remove any Dups //wispDepths = wispDepths.Distinct ().ToList();</td>
<td> 420. 421. 422. 423.</td><td> //setup this wisp in the wisp list WispCoveredFrameltem itd = new WispCoveredFrameltem() ;</td>
<td> 424. 425. 426. 427. 428 .</td><td> itd.wispID = popupRecieve_WispName; itd.frameCountNum = 0; itd.isCurrentlylnClickState = false; itd.currentPixCount = 0; itd.totalPixels = wispDepths.Where(x => x.wispIE == popupReciev<sup>r</sup>e WispName).Count () ;</td>
<td> 429. 430. 431. 432. 433. 434. 435. 436. 437. 438 . 439. 440. 441. 442. 443. 444. 445. 446.</td><td> wispviewlabList.Add(itd); //clear //var t = this.bitmap.Pixelwidth; var j = Pause; pcpupRecieve_WispName = recievePop_tempPoints.Clear (); processPopup = false; //Build XML Values and save to XML files SaveWispsToXML() ; SaveWispDepthsToXML();</td>
Date Reçue/Date Received 2021-11-12
<td> 447. 448 .</td><td> } if (enterViewerMode == true)</td>
<td> 449.</td><td> {</td>
<td> 450.</td><td> //use WispDepths list to loop throught all</td>
<td> coordinates and</td><td></td>
<td> 451.</td><td> //ex: if 25% of the depth of a wisp is</td>
<td> greater than 50mm -</td><td> trigger a click.</td>
<td> 452.</td><td> //you may have to add a touchcount (like</td>
<td> greenscreens or. the</td><td> spaceescreens) to make sure a consistant 25% is</td>
<td colspan="2"> covered over three or four frames.</td>
<td> 453.</td><td> // use KispCoveredFrameCountList for</td>
<td> external touchcounts</td><td></td>
<td> 454.</td><td> //finally, you might have to</td>
<td> 455.</td><td></td>
<td> 456.</td><td> //FRAME_NUM_REQUIRED_FOR_CLICK = 5;</td>
<td> 457.</td><td> //WISP_PERCENT_CCVERAGE_FOR_CLICK = 25; //</td>
<td> percentage</td><td></td>
<td> 458 .</td><td> //WispViewTabList should be filled with</td>
<td> names, but no data.</td><td></td>
<td> 459.</td><td></td>
<td> 460.</td><td> WispViewTabList.Select(c => {</td>
<td> c.currentPixCount =</td><td> 0; return c; ·).ToList();</td>
<td> 461.</td><td></td>
<td> 462.</td><td></td>
<td> 463.</td><td> //string wispDepthListOutput =</td>
<td> 464.</td><td></td>
<td> 465.</td><td> foreach (var di in WispDepths)</td>
<td> 466.</td><td> {</td>
<td> 467.</td><td></td>
<td> 468 .</td><td></td>
<td> 469.</td><td> //throw out the 0's</td>
<td> 470.</td><td> if ( (di.wispPixDepth > 0) &&</td>
<td> (di.wispindex > 0) )</td><td></td>
<td> 471.</td><td> {</td>
<td> 472.</td><td></td>
<td> 473.</td><td> int depth =</td>
<td colspan="2"> depthpixels[di.wispindex];</td>
<td> 474.</td><td> int BaseLineDepth = di.wispPixDepth</td>
<td> 475.</td><td></td>
<td> 476.</td><td> if (depth > 1 && BaseLineDepth > 1)</td>
<td> 477.</td><td> {</td>
<td> 478 .</td><td> var pl =</td>
<td colspan="2"> depthpixels[di.wispindex];</td>
<td> 479.</td><td> if ( (BaseLineDepth - depth ></td>
<td> MIN_DEPTH_CLICK) &&</td><td> (BaseLineDepth - depth < MAX_DEPTH_CLICK))</td>
<td> 480.</td><td> {</td>
<td> 481.</td><td> //count this one point as a</td>
<td> click.</td><td></td>
<td> 482.</td><td> WispViewTabList.First(w =></td>
<td colspan="2"> w.wispID == di.wispID).currentPixCount++;</td>
<td> 483.</td><td></td>
<td> 484 .</td><td> // var tt = 0;</td>
<td> 485.</td><td> }</td>
<td> 486.</td><td> }</td>
Date Reçue/Date Received 2021-11-12
<td> 487.</td><td></td>
<td> 488 .</td><td></td>
<td> 489.</td><td> }</td>
<td> 490.</td><td> Il wispEepthListOutput +=</td>
<td></td><td> di.wispindex.ToString() + + di.wispPixDepth.ToString() + \r\n;</td>
<td> 491.</td><td> }</td>
<td> 492.</td><td></td>
<td> 493.</td><td> //all touch as been calculated - time to</td>
<td></td><td> render a click at the right time.</td>
<td> 494.</td><td> foreach (var wtli in WispViewTabList)</td>
<td> 495.</td><td> (</td>
<td> 496.</td><td> if (wtli.currentPixCount ></td>
<td></td><td> (wtli.totalFixeIs * WISP_FERCENT_COVERAGE_FOR_CLICK))</td>
<td> 497.</td><td> {</td>
<td> 498 .</td><td> wtli.frameCountNum++;</td>
<td> 499.</td><td> }</td>
<td> 5ÛÛ.</td><td> else</td>
<td> 501.</td><td> {</td>
<td> 502.</td><td> wtli.frameCountNum—;</td>
<td> 503.</td><td> }</td>
<td> 504.</td><td></td>
<td> 505.</td><td> //click CR reset</td>
<td> 506.</td><td> if (wtli.frameCountNum >=</td>
<td></td><td> FRAME NUM REQUIRED FOR CLICK)</td>
<td> 507.</td><td> {</td>
<td> 508 .</td><td></td>
<td> 509.</td><td> //VZRTUAL Click</td>
<td> 510.</td><td> uc3.VirtualWispClick(wtli.wispIE.ToString()) ;</td>
<td> 511.</td><td></td>
<td> 512.</td><td> wtli.frameCountMum - 0;</td>
<td> 513.</td><td> wtli.currentPixCount = 0;</td>
<td> 514.</td><td> PauseTouchCounter = 0;</td>
<td> 515.</td><td> PauseTouch = true;</td>
<td> 516.</td><td> PauseOnLongWaitCounter = C;</td>
<td> 517.</td><td> //}</td>
<td> 518.</td><td> }</td>
<td> 519.</td><td> else if (wtli.frameCountNum <= C)</td>
<td> 520.</td><td> {</td>
<td> 521.</td><td> //CLICK RESET</td>
<td> 522.</td><td> wtli.frameCountNum = 0;</td>
<td> 523.</td><td> wtli.isCurrentlylnClickState =</td>
<td></td><td> false;</td>
<td> 524.</td><td> }</td>
<td> 525.</td><td></td>
<td> 526.</td><td></td>
<td> 527.</td><td> }</td>
<td> 528 .</td><td></td>
<td> 529.</td><td></td>
<td> 530.</td><td></td>
<td> 531.</td><td></td>
<td> 532.</td><td></td>
<td> 533.</td><td> }</td>
Date Reçue/Date Received 2021-11-12
<td colspan="4"> 534.</td>
<td> 535. 536.</td><td></td><td> if (depthFrameProcessed && enterTab2 ==</td><td> true</td>
<td> 537. 538 . 539. 540. 541. 542.</td><td></td><td> { //debug //foreach (var item in wispDepths) //{ // depthPixels[item.wispindex] =</td><td> 1;</td>
<td> 543. 544. 545.</td><td></td><td colspan="2"> // //displayMe // int displayindex = item.wispindex</td>
<td> 546. 547.</td><td> BYTES_PER_</td><td> PIXEL; // _disp_ayPixels[displayindex t</td><td> 0] =</td>
<td> 548 .</td><td> Oxff;</td><td> // _displayPixels[displayindex +</td><td> 1] =</td>
<td> 549.</td><td> Oxff;</td><td> // _dispiayPixels[displayindex +</td><td> 2] =</td>
<td> 550.</td><td> Oxff;</td><td> // _displayPixels[displayindex +</td><td> 3] =</td>
<td> 551. 552. 553. 554. 555. 556. 557. 558. 555. 560. 561. 562. 563. 564. 565. 566. 567. 568 . 569. 570. 571. 572. 573. 574. 575. 576. 577.</td><td> Oxff;</td><td> H} this.RenderDepthPixels (); } } H END FRAME_SKIP else { FRAME_SKIP_COUNTER++; if (df != null) { df.Dispose (); 1 if (cf ! = null) { cf.Dispose (); } } // // Process Depth II FrameDescription dFrameDescription</td><td></td>
<td> 578 . 579. 580. 581.</td><td> depthFrams</td><td> .FrameDescription; } catch (Exception ex) { //nothing</td><td></td>
Date Reçue/Date Received 2021-11-12
<td> 582. 583. 584. 585. 586. 587. 588 . 589. 590. 591. 592. 593. 594. 595. 596. 597. 598 . 599. 600. 601. 602. 603. 604. 605. 606. 607. 608 . 609. 610. 611. 612. 613. 614. 615. 616. 617. 618. 619. 620. 621. 622.</td><td> Debug.Writeline(ex); if (df != null) { df.Dispose(); } if (cf != null) { cf.Dispose(); } } finally if (isBitmapLocked) { // this.bitnap.Unlock(); } if (df != null) { df.Dispose (); } if (cf != null) { cf.Dispose (); } } }// end if TouchPause ) private void RenderDepthFixels() < //write image to screen - if it's called this.depthBitmap.WritePixels( new Int32Rect(0, 0, this.depthBitmap.PixelWidth this.depthBitmap.PixelHeight),</td>
<td> 623. 624. 625. 626. 627. 628 . 629. 630.</td><td> depthPixels, this.depthBitmap.PixelWidth, 0); //displayMe _bitrnap.Lock () ; Marshal.Copy(_displayPixels, 0, _bitmap.BackBuffer, _displayPixels.Length);</td>
<td> 631.</td><td> _bitmap.AddDirtyRect(new Int32Rect(0, 0, depthwidth depthHeight)) ;</td>
<td> 632.</td><td> _bitmap.Unlock ();</td>
Date Reçue/Date Received 2021-11-12
633.
634.
635.
636.
637.
638 .
639.
640.
641.
642.
643.
644.
645.
646.
647.
648 .
649.
650.
651.
652.
653.
654.
655.
656.
657.
658 .
659.
660.
661.
662.
663.
664.
665.
666.
667.
668 .
669.
670.
671.
672.
if ( popup != null) { _popup.startimage.Source = this.depthBitmap;
_popup.colorImage.Source = this._bitmap;
} }
III <summary>
III Directly accesses the underlying image buffer of the DepthFrame to
III create a displayable bitmap.
Ill This function requires the /unsafe compiler option as we make use of direct
III access to the native memory pointed to by the depthFrameData pointer.
Ill </summary>
III <param name=<sup>n</sup>depthFrameData>Pointer to the DepthFrame image data</param>
III <param name=depthFrameDataSize>Size of the DepthFrame image data</param>
III <param name=minDepth>The minimum reliable depth value for the frame</param>
III <param name=maxDepth>The maximum reliable depth value for the frame</param>
private unsafe void ProcessDepthFrameData(IntPtr depthFrameData, uint depthFrameEataSize, ushort minDepth, ushort maxDepth)
II depth frame data is a 16 bit value ushort* frameData = (ushort*)depthFrameData;
Π convert depth to a visual representation for (int i = 0; i < (int)(depthFrameDataSize / this.depthFrameDescription.BytesPerPixel) ; ++i) (
II Get the depth for this pixel ushort depth = frameData[i];
II To convert to a byte, we're mapping the depth value to the byte range.
II Values outside the reliable depth range are mapped to 0 (black).
//depthPixels[i] = (byte)(depth >= minDepth &S depth <= maxDepth ? (depth / MapDepthTcByte) : 0);
//this.depthPixels[i] = (byte)(depth);
depthPixels[i] = (byte)(depth >= minDepth && depth <= maxDepth ? depth : Û) ;
}
Date Reçue/Date Received 2021-11-12
673.
674.
675.
676.
677.
678 .
679.
680.
681.
682.
683.
684.
685.
686.
687.
688 .
689.
690.
691.
692.
693.
694.
695.
696.
697.
698 .
699.
700.
701.
702.
703.
704.
705.
706.
707.
708 .
709.
710.
711.
} //listens to key press on keyboard. - for testing, private void OnWindowKeyCp(object sender, KeyEventArgs e) switch (e.Key) { case Key.Fl: var ucs = LogicaiTreeHelper.FindLogicalNode(mainWindow, uc + (tabControl.Selectedlndex + 1).TcString()) as NonAffineTransformControl;
ucs.VirtualWispClick(<sup>n</sup>aaa-lll-bbb); break;
//toggle fullscreen case Key.Fil: var uc =
LogicalTreeHelper.FindLogicalNode(mainWindow, uc + (tabControl.Selectedlndex + 1).ToString()) as NonAffineTransformControl;
var tab =
LogicalTreeHelper.FindLogicalNode(mainWindow, tabGrid + (tabcontrol.Selectedlndex + 1).Testring ()) as Grid;
if (uc != null && tab ! = null) { if (mainWindow.Windowstate == System.Windows.Windowstate.Maximized) { mainWindow.Windowstate = System.Windows.Windowstate.Normal;
mainWindow.Windowstyle = System,Windows.Windowstyle.SingleBorderWindcw;
rootGrid.Children.Remove(uc); tab.Children.Add(uc);
tabControl.Visibility = Visibility.Visible;
} else { mainWindow.Windowstate = System.Windows.Windowstate.Maximized;
mainWindow.Windowstyle = System. Windows.WindowStyle. None ;
tab.Children.Remove(uc);
rootGrid.Children.Add(uc);
tabControl.Visibility =
Visibility.Hidden;
Date Reçue/Date Received 2021-11-12
712.
713.
714.
715.
716.
717.
718.
719.
720.
721.
722.
723.
724.
725.
726.
727.
728 .
729.
730.
731.
732.
733.
734.
735.
736.
737.
738 .
739.
740.
741.
742.
743.
744.
745.
746.
747.
} } break;
case Key.F2: //TEMP functional to reset XML to test setup
Wisp[] wisps = new Wisp[] { new Wisp () {
WispID = aaa-lll-bbb, Name = ccc,
WispPolygon = new WispPolygon() {
Content = gif.gif, ClickContent = gif.gif, CornerPoints = new
Pointcollection(new Point[] { new Point(0, 0), //Coordinates of a top-left corner new Point(0, 100), //Coordinates of a bottom-left corner new Point(100,
0), //Coordinates of a top-right corner new Point(100, 100) //Coordinates of a bottom-right corner
}),
ContentType =
ContentType.Gif,
FrameRate = 0, Loop =
LoopType. Forever, ZCrder = 1 }, ContentPolygon = new
Contentpolygon () { Content =
PetzoldTattoo. jpg, CornerPoints = new
Pointcollection(new Point[] { new Point(100,
0), //Coordinates of a top-left corner new Point(100, 100), //Coordinates of a bottom-left corner new Point(200,
0), //Coordinates of a top-right corner new Point(200, 100) //Coordinates of a bottom-right corner
}),
ContentType = ContentType.Image,
FrameRate = 0,
Loop = (LoopType)2,
Date Reçue/Date Received 2021-11-12
748 .
ZCrder = Ο,
749. ContentOrientation =
<td> o.</td>
<td> 750. Timeout = 3,</td>
<td> 751. }</td>
<td> 752. },</td>
<td> 753. new Wisp ()</td>
<td> 754. {</td>
<td> 755. WispID = aaa-lll-bbb,</td>
<td> 756. Name = ccc,</td>
<td> 757. WispPolygon = new</td>
<td> WispPolygon()</td>
<td> 758 . {</td>
<td> 759. Content = vidl.wmv.</td>
<td> 760. ClickContent = null,</td>
<td> 761. CcrnerPoints = new</td>
<td> PointCollectior. (new Point [] {</td>
<td> 762. new Point(0,</td>
<td> 100), //Coordinates of a top-left corner</td>
<td> 763. new Point(0,</td>
<td> 200), //Coordinates of a bottom-left corner</td>
<td> 764. new Point(100,</td>
<td> 100), //Coordinates of a top-right corner</td>
<td> 765. new Point(100,</td>
200) //Coordinates of a bottom-right corner
766.)),
67. ContentType=
ContentType.Video,
68 . FrameRate =0,
769. Loop = (LoopType)2,
770. ZCrder = 4
771.},
772. ContentPolygon = r.ew
Contentpolygon ()
773.{
774. Content =
PetzoldTattoo. jpg,
775. CcrnerPoints = new
PointCollectior. (new Point [] {
776. new Point(100,
0), //Coordinates of a top-left corner
777. new Point(100,
100), //Coordinates of a bottom-left corner
778. new Point(200,
0), //Coordinates of a top-right corner
779. new Point(200,
100) //Coordinates of a bottom-right corner
780. )),
781.
ContentTyoe.Image,
782.
783.
784.
ContentType =
FrameRate = 0,
Loop = (LoopType)2, ZCrder = 0,
Date Reçue/Date Received 2021-11-12
785.
Contentorientation =
0,
786.
Timeout = 3,
787.
788 .
789.
790.
791.
792.
793.
WispPolygon()
794.
795.
wisp png sequence,
796.
797.
PointCollectior. (new Point [] { }
}, new Wisp () {
WispID = aaa-222-bbb, Name = ccccxzczxxcz, WispPolygon = new {
Content =
ClickContent = null, CcrnerPoints = new
<td> 798 .</td><td> 200), //Coordinates</td><td> of</td><td> a</td><td> top-left corner</td><td> new</td><td> Point(0,</td>
<td> 799.</td><td> 300), //Coordinates</td><td> of</td><td> a</td><td> bottom-left corner</td><td> new</td><td> Point(0,</td>
<td> 800 .</td><td> 200), //Coordinates</td><td> of</td><td> a</td><td> top-right corner</td><td> new</td><td> Point(100</td>
<td> 801.</td><td></td><td></td><td></td><td></td><td> new</td><td> Point(100</td>
300) //Coordinates of a bottom-right corner
802.J),
803. ContentType=
ContentType.PngSeq,
804. FrameRate =60,
805. Loop = (LoopType)2,
806. ZCrder = 2
807.},
808 .
ContentPolygon = new
Contentpolygon ()
809.{
810. Content =
PetzoldTattoo. jpg,
811. CcrnerPoints = new
PointCollectior. (new Point [] {
812. new Point(100,
0), //Coordinates of a top-left corner
813. new Point(100,
100), //Coordinates of a bottom-left corner
814. new Point(200,
0), //Coordinates of a top-right corner
815. new Point(200,
100) //Coordinates of a bottom-right corner
816. }),
817.
ContentTyoe.Image, 818.
819.
820.
ContentType =
FrameRate = 0,
Loop = (LoopType)2, ZCrder = 0,
Date Reçue/Date Received 2021-11-12
821.
Contentorientation =
822 .
823.
824.
825.
826.
827.
828 .
829.
new
Wisp()
Timeout = 3
WispPolygon()
WisplD = aaa-lll-bbb, Name = cccwqqweqw, WispPolygon = new
830 .
831.
Content =
832.
833 .
wisp_png_sequence2.
ClickContent = null
CcrnerPoints = new
PointCollectior. (new Point [] {
<td> 834.</td><td> 300), //Coordinates</td><td> of</td><td> a</td><td> top-left corner</td><td> new</td><td> Point(0,</td>
<td> 835.</td><td> 400), //Coordinates</td><td> of</td><td> a</td><td> bottom-left corner</td><td> new</td><td> Point(0,</td>
<td> 836.</td><td> 300), //Coordinates</td><td> of</td><td> a</td><td> top-right corner</td><td> new</td><td> Point(100</td>
<td> 837.</td><td></td><td></td><td></td><td></td><td> new</td><td> Point(100</td>
400) //Coordinates of a bottom-right corner
838 .
833.
ContentType =
ContentType.Text
840.
841.
842.
843.
844 .
FrameRate = 60, Loop = (LoopType)2, ZCrder = 5
ContentPolygon = new
Contentpolygon ()
845.
846.
Content
847.
PetzoldTattoo. jpg,
CcrnerPoints = new
PointCollectior. (new Point [] {
848 .
new
Point(100
843.
0), //Coordinates of a top-left corner new
Point(100
100), //Coordinates of a bottom-left corner
850.
new
Point(200
851.
852.
853.
0), //Coordinates of a top-right corner new
Point(200
100) //Coordinates of a bottom-right corner
ContentType =
ContentType.Image,
854.
855.
856.
FrameRate = 0, Loop = (LoopType)2 zcrder = 0,
Date Reçue/Date Received 2021-11-12
857.
858 .
859.
860.
861.
862.
863.
864.
865.
866.
867.
868 .
869.
870.
871.
872.
873.
874.
875.
876.
877.
878 .
879.
880 .
881.
882 .
883 .
884.
885.
886.
887 .
888 .
889.
890.
891.
892.
Contentorientation = 0,
Timeout = 3, } }, new Wisp () {
WisplD = aaa-lll-bbb, Name = cccasdas, WispPolygon = new
WispPolygon() { Content = PetzoldTattoo. jpg, ClickContent = rotate.png, CornerPoints = new Pointcollection(new Point[] { new Point(0, 400), //Coordinates of a top-left corner new Point(0, 500), //Coordinates of a bottom-left corner new Point(100, 400), //Coordinates of a top-right corner new Point(100, 500) //Coordinates of a bottom-right corner
}),
ContentType = ContentType.Image,
FrameRate = 60,
Loop = (LoopType)2, ZCrder = 0 b
Contentpolygon = new Contentpolygon () { Content = PetzoldTattoo. jpg, CornerPoints = new Pointcollection(new Point [] { new Point(100, 0), //Coordinates of a top-left corner new Point(100, 100), //Coordinates of a bottom-left corner new Point(200, 0), //Coordinates of a top-right corner new Point(200,
100) //Coordinates of a bottom-right corner
}),
ContentType = ContentType.Image,
FrameRate = 0,
Loop = (LoopType)2, ZCrder = 0,
Date Reçue/Date Received 2021-11-12
893.
Contentorientation =
<td></td><td> 0,</td>
<td> 894. 895. 896. 897. 898 . 899. 900. 901. 902.</td><td> Timeout = 3, } } }; //ucl.Wisps = wisps; using (var fs = File.Create(test.xml)) { XmlSerializer xs = new XmlSerializer(typeof(Wisp[]), new Type[] {</td>
<td> 903. 904. 905. 906. 907. 908 . 909. 910. 911. 912. 913. 914. 915. 916.</td><td> typeof(Wisp), typeof(Contentpolygon) typeof (WispPolygor.), typeof(Polygon), typeof(ContentType), typeof(LoopType) }); xs.Serialize(fs, wisps); } break; } } private void OnViewerMouseüp(object sender, MouseButtonEventArgs e)</td>
<td> 917. 918. 919. 920. 921. 922.</td><td> { enterViewerMode = true; enterTab2 = false; } private void OnSetupMouseUp(object sender, MouseButtonEventArgs e)</td>
<td> 923. 924. 925. 926. 927.</td><td> { enterViewerMode = false; enterTab2 = false; ) private void OnTab2MouseUp(object sender, MouseButtonEventArgs e)</td>
<td> 928 . 929. 930. 931. 932. 933. 934. 935.</td><td> enterTab2 = true; enterViewerMode = false; //if popup is closed if (_popup != null) ( _popup.startimage.Source = new Bitmapimage(new Uri (@pack://siteoforigin:,,,/Spaceeblk.jpg)) ;</td>
<td> 936. 937. 938 . 939. 940.</td><td> } if (_popup == null) { //creating a popup _popup = new PopupWindow();</td>
Date Reçue/Date Received 2021-11-12
<td> 941. 942. 943. 944. 945.</td><td> _popup.Closed += OnPopupClosed; //finding out screen configuration var allScreens = System.Windows.Forms.Screen.AllScreens;</td>
<td> 946. 947.</td><td> //by default destination screen is the first System.Windows.Forms.Screen destScreen = allScreens[0];</td>
<td> 948 . 949. 950. 951. 952.</td><td> //if there are more than one screen if (allScreens.Length > 1) { //finding out current screen var currentscreen = System.Windows. Forms. Screen.FromFoint(new System.Erawing.Point((int)Left, (int)Top)) ;</td>
<td> 953.</td><td> var screenindex = Array.IndexOf(allScreens, currentscreen);</td>
<td> 954. 955.</td><td> //destination screen is next destScreen = allScreens[(screenindex + 1) % allScreens.Length];</td>
<td> 956. 957. 958 .</td><td> } //placing popup in the middle of destination screen _popup.Left = destScreen.WorkingArea.Left + (destScreen.WorkingArea.Width - _popup.Width) / 2;</td>
<td> 959.</td><td> _popup.Top = destScreen.WorkingArea.Top + (destScreen.WorkingArea.Height - _popup.Height) / 2;</td>
<td> 960. 961. 962. 963. 964. 965. 966. 967. 968 . 969. 970. 971. 972. 973. 974.</td><td> //copy wisps to popup _popup.NonAffineIransformControl.Wisps = uc2.Wisps; //showing popup popup. Shew () ; } else //else focusing it { _popup.Focus (); ) } /// <summary> III Handles popup closed event. Removes all handlers and links.</td>
<td> 975. 976. 977. 978 . 979. 980. 981. 982. 983. 984. 985.</td><td> Ill </summary> III <param name=sender></param> III <param name=<sup>n</sup>eX/param> private void OnPopupClosed(object sender, EventArcs e) _popup.Closed -= OnPopupClosed; _popup = null; III <summary> III Handles popup NonAffineTransformControl loaded event.</td>
Date Reçue/Date Received 2021-1 ^<sub>STnvrE SHEET</sub> (RULE 26)
<td> 986. 987. 988 . 989. 990. 991. 992. 993. 994. 995.</td><td> II! </summary> /// Kparam name=sender></param> III <param name=eX/param> private void OnMainWindowLoaded(object sender, RoutedEventArgs e)</td>
<td> 996. 997. 998 . 999. 1000.</td><td> UpdateCornerPoints(); } private void OnMainWindowLocationChanged(object sender, EventArgs e)</td>
<td> 1001. 1002. 1003. 1004.</td><td> UpdateCornerPoints(); )</td>
<td> 1005.</td><td> private void OnMainWindowSizeChanged(object sender, SizeChangedEventArgs e)</td>
<td> 1006. 1007. 1008. 1009. 1010. 1011. 1012. 1013.</td><td> { UpdateCornerPoints(); } private void UpdateCornerPoints!) _topLeft = PointToScreen(new Point ()); _bottomRight = new Point(_topLeft.X + mainWindow.Actualwidth, topLeft.Y + nainWindow.ActualHeight);</td>
<td> 1014. 1015. 1016. 1017. 1018. 1019. 1020. 1021. 1022. 1023.</td><td> } private Popupwindow _popup; private Point _topLeft; private Point _bottomRight; //loads the system in viewer mode and in full screen. - If there is a system crash, the moncter system will detect it and relaunch the program in this state.</td>
<td> 1024. 1025. 1026. 1027. 1028. 1029. 1030.</td><td> public void startAppinFullView() //wait until the program loads int ct = 0; DispatcherTimer switchTabTimer = new DispatcherTimer() ; switchTabTimer.Interval = TimeSpan.FromSeconds(1); switchTabTimer.Tick += (object timersender, EventArgs timerE) =></td>
<td> 1031. 1032.</td><td> { ct++;</td>
ΊΊ
Date Reçue/Date Received 2021-11-12
<td> 1033.</td><td> //switchTabTimer.StopO;</td>
<td> 1034.</td><td> if (et > 0)</td>
<td> 1035.</td><td> {</td>
<td> 1036.</td><td> //viewer tab</td>
<td> 1037.</td><td> tabcontrol.Selectedlndex = 2;</td>
<td> 1038.</td><td> switchTàbTiiriér.Stôp () ;</td>
<td> 1033.</td><td> switchTabTimer = null;</td>
<td> 1040.</td><td> // System.Windows.MessageBox.Show(PREP) ;</td>
<td> 1041.</td><td> var uc =</td>
<td></td><td> LogicalTreeHelper.FindLogicalNode(mainWindow, uc +</td>
<td></td><td> (tabControl.Selectedlndex + 1).TcString()) as</td>
<td></td><td> NonAffineTransformControl;</td>
<td> 1042.</td><td> var tab =</td>
<td></td><td> LogicalTreeHelper.FindLogicalNode(mainWindow, tabGrid +</td>
<td></td><td> (tabContrcl.Selectedlndex + 1).TcString()) as Grid;</td>
<td> 1043.</td><td> if (uc != null && tab != null)</td>
<td> 1044.</td><td> {</td>
<td> 1045.</td><td></td>
<td> 1046.</td><td> mainWindow.Windowstate =</td>
<td></td><td> System.Windows.Windowstate.Maximized;</td>
<td> 1047.</td><td> mainWindow.Windowstyle =</td>
<td></td><td> Sy s tern.Ki ndows.Wi ndowS ty1e.No ne ;</td>
<td> 1048.</td><td></td>
<td> 1043.</td><td> tab.Children.Remove(uc);</td>
<td> 1050.</td><td> rootGrid.Children.Add(uc);</td>
<td> 1051.</td><td> tabContrcl.Visibility = Visibility.Hidden;</td>
<td> 1052.</td><td></td>
<td> 1053.</td><td> enterViewerMode = true;</td>
<td> 1054.</td><td> enterTabz = false;</td>
<td> 1055.</td><td> //System.Windows.MessageBox. Show (IT</td>
<td></td><td> WORKS);</td>
<td> 1056.</td><td></td>
<td> 1057.</td><td> //CAUSE ERROR TO TEST APPLICATION CRASH</td>
<td> 1058.</td><td> // int t = 0 / (ct - 1);</td>
<td> 1059.</td><td></td>
<td> 1060.</td><td> }</td>
<td> 1061.</td><td> }</td>
<td> 1062.</td><td> );</td>
<td> 1063.</td><td> switchTabTimer. Start () ;</td>
<td> 1064.</td><td></td>
<td> 1065.</td><td></td>
<td> 1066.</td><td> }</td>
<td> 1067.</td><td></td>
<td> 1068.</td><td> //DEPTHS XML</td>
<td> 1063.</td><td> private void SaveWispsToXML()</td>
<td> 1070.</td><td> {</td>
<td> 1071.</td><td> using (var fs =</td>
<td></td><td> System.IO.File.Create (_WispCoveredFrameItem_XMLFile) )</td>
<td> 1072.</td><td> {</td>
<td> 1073.</td><td> XmlSerializer xs = new</td>
<td></td><td> Xmlserializer (typeof(List<wispCcveredFrameltem>), new Type[] {</td>
<td> 1074.</td><td> typeof(List<WispCoveredFrameItem>)</td>
<td> 1075.</td><td> });</td>
<td> 1076.</td><td> xs.Serialize(fs, WispViewTabList);</td>
Ή
Date Reçue/Date Received 2021-11-12
1077.
1078. fs.CloseO;
1079. }
<td> 1080. 1081. 1082. 1083.</td><td> private void LoadWispsFrcmXML() { if ( ! string.IsNullOrEmpty(_WispCoveredFrameItem_XMLFile) && System.IO.File.Exists ( WispCoveredFrameltem XMLFile))</td>
<td> 1084. 1085. 1086. 1087.</td><td> { try { using (var fs = System.IO.File.OpenRead(_WispCoveredFrameItem_XMLFile))</td>
<td> 1088. 1089.</td><td> { XmlSerializer xs = new XmlSerializer(typeof(List<WispCoveredFrameItem>), new Type[] {</td>
<td> 1090. 1091. 1092.</td><td> typeof(WispCoveredFrameltem) }); WispViewIabList = (List<WispCoveredFrameItem>)xs.Deserialize(fs);</td>
<td> 1093. 1094. 1095.</td><td> } } catch { }</td>
<td> 1096. 1097. 1098. 1099. 1100. 1101.</td><td> ) ) private void SaveWispDepthsToXML() using (var fs = System.IO.File.Create ( WispDepths XMLFile))</td>
<td> 1102. 1103.</td><td> { XmlSerializer xs = new XmlSerializer(typeof(List<WispInteractiveData>), new Type[] {</td>
<td> 1104. 1105. 1106. 1107. 1108. 1109. 1110. 1111. 1112. 1113. 1114.</td><td> typeof(List<WispInteractiveData>) )); xs.Serialize(fs, wispDepths); fs.Close (); ) } private void LoadWispDepthsFromXML() J</td>
<td> 1115.</td><td> if ( ! string.IsNullOrEmpty(_WispDepths_XMLFile) && System.IO.File.Exists(_WispDepths_XMLFile))</td>
<td> 1116. 1117. 1118. 1119.</td><td> ( try { using (var fs = System.lO.File.OpenRead( wispDepths_XMLFile))</td>
<td> 1120. 1121.</td><td> { XmlSerializer xs = new XmlSerializer(typeof(List<WispInteractiveData>), new Type[] {</td>
Date Reçue/Date Received 2021-11-12 typeof(WispInteractiveData)
1122.
1123. });
<td> 1124.</td><td> wispDepths = (List<WisoInteractiveData>)xs.Deserialize(fs);</td>
<td> 1125. 1126. 1127. 1128. 1129. 1130. 1131.</td><td> } } catch { } ) }</td>
1132. }
1133.
1134.
1135. }
1136.
Date Reçue/Date Received 2021-11-12
<td> 1.</td><td> using System;</td>
<td> 2.</td><td> using System.Collections.Generic;</td>
<td> 3.</td><td> using System.Linq;</td>
<td> 4.</td><td> using System.Text;</td>
<td> 5.</td><td> using System.Threading.Tasks;</td>
<td> 6.</td><td> using System.Windows;</td>
<td> 7.</td><td> using System.Windows.Controls;</td>
<td> 8.</td><td> using System.Windows.Data;</td>
<td> 9.</td><td> using System. Windows. Documents;</td>
<td> 10.</td><td> using System.Windows.Input;</td>
<td> 11.</td><td> using System.Windows.Media;</td>
<td> 12.</td><td> using System.Windows.Media.Imagir.g;</td>
<td> 13.</td><td> using System.Windows.Media.Media3D;</td>
<td> 14.</td><td> using System.Windows.Navigation;</td>
<td> 15.</td><td> using System.Windows.Shapes;</td>
<td> 16.</td><td> using System. Windows. Threading;</td>
<td> 17. 18.</td><td> using System.Xml.Serialization;</td>
<td> 19.</td><td> namespace NonAffineTransfcrm</td>
<td> 20.</td><td> {</td>
<td> 21.</td><td> III <summary></td>
<td> 22.</td><td> III Interaction logic for NonAffineTransformControl.xaml</td>
<td> 23.</td><td> III </summary></td>
<td> 24.</td><td> public partial class NonAffineTransformControl ; UserControl</td>
<td> 25.</td><td> {</td>
<td> 26.</td><td> private class RenderedPolygon</td>
<td> 27.</td><td> •</td>
<td> 28.</td><td> III <summary></td>
<td> 29.</td><td> III Rendering planes (meshes)</td>
<td> 30.</td><td> III </summary></td>
<td> 31. 32.</td><td> public MeshGeometry3D Mesh;</td>
<td> 33.</td><td> III <summary></td>
<td> 34.</td><td> III Transforming matrices</td>
<td> 35.</td><td> III </summary></td>
<td> 36. 37.</td><td> public MatrixTransform3D MatrixTransform;</td>
<td> 38.</td><td> III <summary></td>
<td> 39.</td><td> III Corner points of meshes</td>
<td> 40.</td><td> III </summary></td>
<td> 41. 42.</td><td> public Point3D[] PointsTransformed;</td>
<td> 43.</td><td> III <summary></td>
<td> 44.</td><td> III Collection of WISP outlines</td>
<td> 45.</td><td> III </summary></td>
<td> 46. 47.</td><td> public PathFigure Outline;</td>
<td> 48.</td><td> III <summary></td>
<td> 49.</td><td> III Collection of WISP outline paths</td>
<td> 50.</td><td> III </summary></td>
<td> 51. 52.</td><td> public Path Outlinepath;</td>
<td> 53.</td><td> III <summary></td>
<td> 54.</td><td> III Connected control</td>
Date Reçue/Date Received 2021-11-12
<td> 55. 56.</td><td> Ht </summary> public FrameworkElement Control;</td>
<td> 57. 58. 59. 60. 61. 62.</td><td> III <summary> III Collection of WISP materials III </summary> public DiffuseMaterial Material;</td>
<td> 63. 64. 65. 66. 67. 68.</td><td> III <summary> III Polygon that is being rendered III <l3\WSi!A^> public Polygon Parent;</td>
<td> 69. 70</td><td> private class RenderedDefaultPolygon ; RenderedPolygon</td>
<td> 71. 72. 73. 74. 75.</td><td> III <summary> III ID of default polygon III </summary> public string ID;</td>
<td> 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87.</td><td> III <summary> III How many times it's requested to hide III </summary> public int Hidecount; } private class RenderedWisp III <summary> III Rendered Wisp polygon III </summary> public RenderedPolygon WispPolygon;</td>
88.
<td> 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105.</td><td> Ill <summary> III Rendered content polygon /// </$ummary> public RenderedPolygon ContentPclygon; III <summary> III Wisp that is being rendered III </summary> public Wisp Parent; III <summary> III Determines whether concent polygons is shown III </summary> public bool CcntentPolygonShown; III <summary> III Backup of content polygon to restore after making unwanted changes</td>
<td> 106. 107.</td><td> III </summary> public Contentpolygon ContentPolygonBackup;</td>
Date Reçue/Date Received 2021-11-12
<td> 108.</td><td></td>
<td> 109.</td><td> /// <summary></td>
<td> 110.</td><td> III Timer which hides content polygon on timeout</td>
<td> 111.</td><td> III </summary></td>
<td> 112.</td><td> public DispatcherTimer HideContentPolygonTimer;</td>
<td> 113.</td><td></td>
<td> 114.</td><td> III <summary></td>
<td> 115.</td><td> III Media player which plays click sounds</td>
<td> 116.</td><td> III </summary></td>
<td> 117.</td><td> public MediaPlayer MediaPlayer;</td>
<td> 118.</td><td> }</td>
<td> 119.</td><td></td>
<td> 120.</td><td> III <summary></td>
<td> 121.</td><td> III Shows priority of mesh dragging over vertex dragging.</td>
<td> 122.</td><td> Ill Set to 1 to disable vertex dragging.</td>
<td> 123.</td><td> Ill Set to 0 to disable mesh dragging.</td>
<td> 124.</td><td> Ill Balanced values are 0.6-0.7 .</td>
<td> 125.</td><td> III </summary></td>
<td> 126.</td><td> private const double MeshDraggingWeight = 0.65;</td>
<td> 127.</td><td></td>
<td> 128.</td><td> III <summary></td>
<td> 129.</td><td> III Shows how far next rendering plane would be placed</td>
<td> 130.</td><td> III </summary></td>
<td> 131.</td><td> private const double ZIncrement = -10.0;</td>
<td> 132.</td><td></td>
<td> 133.</td><td> private static readonly Foint3D[] DefaultCornerPoints = new</td>
<td></td><td> Point3D[] {</td>
<td> 134.</td><td> new Point3D(-0.5, 0.5, 0),</td>
<td> 135.</td><td> new Point3D(-0.5, -0.5, 0),</td>
<td> 136.</td><td> new Point3D(0.5, 0.5, 0),</td>
<td> 137.</td><td> new Point3D(0.3, -0.5, 0)</td>
<td> 138.</td><td> );</td>
<td> 139.</td><td></td>
<td> 140.</td><td> public static readonly Dependencyproperty WispsProperty;</td>
<td> 141.</td><td> public static readonly DependencyProperty</td>
<td></td><td> DefaultPolygonProperty;</td>
<td> 142.</td><td> public static readonly Dependencyproperty</td>
<td></td><td> StorageFileProperty;</td>
<td> 143.</td><td> public static readonly Dependencyproperty</td>
<td></td><td> ShowContentProperty;</td>
<td> 144.</td><td> public static readonly DependencyProperty</td>
<td></td><td> ShowOutlinesProperty;</td>
<td> 145.</td><td> public static readonly DependencyProperty ReadOnlyProperty;</td>
<td> 146.</td><td> public static readonly DependencyProperty PlaySour.dProperty</td>
<td> 147.</td><td></td>
<td> 148.</td><td> static NonAffineTransformControl()</td>
<td> 149.</td><td></td>
<td> 150.</td><td> WispsProperty = DependencyProperty.Register (Wisps,</td>
<td></td><td> typeof(Kisp[]), typeof(NonAffineTransformControl)) ;</td>
<td> 151.</td><td> DefaultPolygonProperty =</td>
<td></td><td> Dependencyproperty. Register ( DeraultPolygons '*, typeof(DefaulrPolygon[]), typeof(NonAffineTransformControl)) ;</td>
Date Reçue/Date Received 2021-11-12
<td> 152.</td><td> StorageFilePrcperty =</td>
<td></td><td> DependencyProperty.Register(Storage, typeof(string), typeof(NonAffineTrans formControl)) ;</td>
<td> 153.</td><td> ShowContentPrcperty = Dependencyproperty.Register(ShowContent, typeof(bool), typeof(NonAffineTransformControl), new PropertyMetadata(true)) ;</td>
<td> 154.</td><td> ShowoutlinesProperty = Dependencyproperty.Register(Showoutlines, typeof(bool), typeof(NonAffineTransformControl), new PropertyMetadata(true)) ;</td>
<td> 155.</td><td> ReadOnlyProperty = Dependencyproperty.Register(Readonly, typeof(bool), typeof(NonAffineTransformControl), new PropertyMetadata(false)) ;</td>
<td> 156.</td><td> PlaySoundProperty = Dependencyproperty.Register(PlaySound, typeof(bool), typeof(NonAffineTransformControl), new PropertyMetadata(false)) ;</td>
<td> 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167.</td><td> ) public NonAffineTransformControl() InitializeComponent() ; Loaded += OnNonAffineTransformCcntrolLcaded; SizeChanged += OnNonAffineTransformControlSizeChanged; } private void OnHideContentPolygonTimerTick(object sender, EventArgs e)</td>
<td> 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181.</td><td> var fe = (sender as DispatcherTimer); if (fe == null) return; var rw = fe.Tag as RenderedWisp; if (rw == null) return; HidecontentPolygon(rw); ) /// <summary> 1/Î Gets or sets collection of polygons which is used to display images/videos/etc.</td>
<td> 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193.</td><td> Ill </summary> public Wisp[] Wisps get { return (Wisp[])GetValue(WispsProperty); } set { SetValue(WispsProperty, value); if ( !_internalChange && _loaded) Initialize (); UpdateCornerPointPositions(); }</td>
Date Reçue/Date Received 2021-11-12
<td> 194. 195. 196. 197. 198.</td><td> } } /// <summary> /// Gets or sets collection of polygons which is used to display images/videos/etc.</td>
<td> 199. 200. 201. 202.</td><td> III </summary> public Defaultpolygon[] Defaultpolygons get { return (DefaultPolygon[])GetValue(DefaultPolygonProperty); }</td>
<td> 203. 204. 205. 206. 207. 208 . 209. 210. 211. 212. 213. 214. 215.</td><td> set { SetValue(DefaultPolygonProperty, value); //if (! internalchange && loaded) //{ II Initialize (); // UpdateCornerPointPositions (); //} } J III <summary> III Gets or sets path to xml file where control autosaves and loads Wisps</td>
<td> 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227.</td><td> III </summary> public string StorageFile get { return (string)GetValue(StorageFileProperty); } set { SetValue(StorageFileProperty, value); } } III <suinniary> III Gets or sets value indication whether content of wisp polygons is shown.</td>
<td> 228 . 229. 230. 231. 232. 233. 234. 235.</td><td> Ill </summary> public bool ShowCcntent get { return (bool)GetValue(ShowContentProperty); } set { SetValue(ShowContentProperty, value); viewport3d.Visibility = value ? Visibility.Visible Visibility.Hidden;</td>
<td> 236. 237. 238 . 239. 240.</td><td> } } III <suinmary> III Gets or sets value indicating whether cutlines and controls of content polygons are shown.</td>
<td> 241.</td><td> Ill </summary></td>
Date Reçue/Date Received 2021-11-12
<td> 242. 243. 244. 245. 246. 247. 248 .</td><td> public bool ShowOutlines get { return (bool)GetValue(ShowOutlinesProperty); } set { Setvalue(ShowOutlinesProperty, value); overlay.Visibility = value ? Visibility.Visible : Visibility.Hidden;</td>
<td> 249. 250. 251. 252. 253.</td><td> } ) III <summary> III Gets or sets value indicating whether user able to move polygons.</td>
<td> 254. 255. 256. 257. 258 . 259. 260. 261. 262. 263. 264. 265.</td><td> Ill </§ummary> public bool Readonly get { return (bool)GetValue(ReadOnlyProperty); } set { SetValue(ReadOnlyProperty, value); } ) III <summary> III Gets or sets value indicating whether control should play click sounds.</td>
<td> 266. 267. 268 . 269. 270. 271. 272. 273. 274. 275. 276. 277. 278 . 279. 280. 281. 282. 283. 284. 285. 286. 287. 288 . 289. 290. 291. 292.</td><td> Ill </summary> public bool PlaySound get { return (bool)GetValue(PlaySoundProperty); ; set { SetValue(PlaySoundProperty, value); ) } public void VirtualWispClick(String wispID) for (int i = 0; i < renderedWisps.Length; i++) { if (_renderedWisps[i].Parent.WispID == wispID) { ShowContentFolygon(_renderedWisps[i]) ; break; } } ) III <summery> III Returns a wisp at specified location III </summary> III <param name=pointx/param> III <returnsx/rerurns></td>
Date Reçue/Date Received 2021-11-12
<td> 293.</td><td> public Wisp GetWispAtPoint(Point point)</td>
<td> 294.</td><td></td>
<td> 295.</td><td> var wisps = Wisps;</td>
<td> 296.</td><td> if (wisps == null)</td>
<td> 297. 298 .</td><td> return null;</td>
<td> 299.</td><td> var resultMesh = GetMeshAtPoint(point);</td>
<td> 300.</td><td> if (resultMesh == null)</td>
<td> 301. 302.</td><td> return null;</td>
<td> 303.</td><td> var meshindex = Array.IndexOf(_renderedWisps.Select -> rw.WispPolygon.Mesh).ToArrayO, resultMesh.MeshHit);</td>
<td> 304.</td><td> if (meshindex >= 0 && meshindex < wisps.Length)</td>
<td> 305.</td><td> {</td>
<td> 306. 307.</td><td> var resultwisp = wisps[meshindex];</td>
<td> 308 .</td><td> return resultwisp;</td>
<td> 309. 310.</td><td> )</td>
<td> 311.</td><td> return null;</td>
<td> 312. 313.</td><td> J</td>
<td> 314.</td><td> III <summary></td>
<td> 315.</td><td> III Returns a Wisp at specified location</td>
<td> 316.</td><td> III </summary></td>
<td> 317.</td><td> III <param name=point></param></td>
<td> 318.</td><td> III <returnsx/returns></td>
<td> 319.</td><td> public Wisp GetWispAtPoint(double x, double y)</td>
<td> 320.</td><td> -</td>
<td> 321.</td><td> return GetWispAtPoint(new Point(x, y) ) ;</td>
<td> 322. 323.</td><td> }</td>
<td> 324.</td><td> III <summary></td>
<td> 325.</td><td> III Returns a Wisp ID at specified location</td>
<td> 326.</td><td> III </summary></td>
<td> 327.</td><td> Hi <param name=<sup>n</sup>point></param></td>
<td> 328 .</td><td> Hi <returnsx/murn$></td>
<td> 329.</td><td> public string GetWispIDAtPoint(Point point)</td>
<td> 330.</td><td> <</td>
<td> 331.</td><td> var wisp = GetWispAtPoint(point);</td>
<td> 332.</td><td> return wisp != null ? wisp.WispID : null;</td>
<td> 333. 334.</td><td> }</td>
<td> 335.</td><td> III <summary></td>
<td> 336.</td><td> III Returns a Wisp ID at specified location</td>
<td> 337.</td><td> III </summary></td>
<td> 338 .</td><td> III <param name=<sup>n</sup>pointX/param></td>
<td> 339.</td><td> III <returnsx/returns></td>
<td> 340.</td><td> public string GetWispIDAtPoint(double x, double y)</td>
<td> 341.</td><td></td>
<td> 342.</td><td> return GetWispIDAtPoint(new Point(x, y) ) ;</td>
<td> 343. 344.</td><td> }</td>
(rw
Date Reçue/Date Received 2021-11-12
<td> 345.</td><td> protected override void OnMouseLeftButtonDown(MouseButtonEventArgs args)</td>
<td> 346. 347.</td><td> Point pt = args.GetPcsition(viewport3d);</td>
<td> 348 . 349. 350. 351. 352.</td><td> var resultMesh = GetMeshAtPoint(pt); if (resultMesh == null) return;</td>
<td> 353.</td><td> var result = _renderedWisps.FirstOrDefault(rw => rw.WispPolygon.Mesh == resultMesh.MeshHit);</td>
<td> 354. 355. 356. 357. 358 . 359. 360. 361.</td><td> if (result !- null) { _draggingWisp = result; draggingPolygon = result.WispPolygon; } else { result = _renderedWisps.FirstOrDefault(rw => rw.ContentPolygonShown && rw.Contentpolygon.Mesh == resultMesh.MeshHit);</td>
<td> 362. 363. 364. 365. 366. 367. 368 . 369. 370.</td><td> if (result != null) { _draggingWisp = result; _draggingPolygon = result.ContentPolycon; _isDraggingContent = true; ) else { var defaultpolygon = _renderedDefaultPolygons.FirstOrDefault(rdp => rdp.Mesh == resultMesh.MeshHit);</td>
<td> 371. 372. 373. 374. 375. 376. 377. 378 . 379. 380.</td><td> if (defaultFolygon != null) { _draggingPolygon = defaultpolygon; } else { return; } } }</td>
381.
<td> 382.</td><td> if ((Readonly _renderedWisps.Any(rw => rw.ContentPolygonShown && rw.Contentpolygon != _draggingPolygon && rw.WispPolygon != _draggingPolygon))</td>
<td> 383. 384. 385. 386. 387. 388 . 389.</td><td> { _draggingWisp = null; _draggingPolygon = null; isDragging = false; -isDraggingConter.t = false; return; }</td>
390.
Date Reçue/Date Received 2021-11-12
<td> 391.</td><td> var diff12 = resultMesh.VertexWeightl resultMesh.VertexWeight2;</td>
<td> 392.</td><td> var diff13 = resultMesh.VertexWeightl resultMesh.VertexWeight3;</td>
<td> 393.</td><td> var diff23 = resultMesh.Vertexweight? resultMesh.VertexWeight3;</td>
<td> 394. 395. 396.</td><td> II Determine if the mouse within central part of mesh, if (Math.Abs(diff12) < MeshDraggingWeight && Math.Abs(diff13) < MeshDraggingWeight && Math.Abs(diff23) < MeshDraggingWeight)</td>
<td> 397. 398 . 399. 400. 401. 402. 403.</td><td> { draggingVertexIr.dex = -1; } II Determine which vertex the mouse is closest to. else if (diffl2 > 0) { _draggingVertex!r.dex = diffl3 > 0 ? resultMesh.Vertexlndexl : resultMesh.Vertexlndex3;</td>
<td> 404. 405. 406. 407.</td><td> } else { _draggingVertexIr.dex - diff23 > 0 ? resultMesh.Vertexlndex2 : resultMesh.Vertexlndex3;</td>
<td> 408 . 409. 410. 411. 412. 413. 414. 415. 416.</td><td> } _startDraggingMousePcint = pt; if (!Readonly) { II Get current transformed points, for (int i = 0; i < 4; i++) { _draggingPolygon.PointsTransformed[i] = _draggingPolygon.MatrixTransform.Matrix.Transform(_draggir.gPolygon.M esh.Positions[i]) ;</td>
<td> 417. 418. 419. 420.</td><td> } if (_draggingvertex:ndex >= 0) { //_draggingPolygon.PointsTransformed[_draggingVertex!ndex] = Simple2Etc3D(viewport3d, pt, _draggingPolygon.PointsTransformed[_draggingVertex!ndex].2) ;</td>
<td> 421.</td><td> //_draggingPolygon.MatrixTrans form.Matrix = CalculateNonAffineTransform(_draggingPolygon.PointsTransformed);</td>
<td> 422. 423. 424. 425. 426.</td><td> } else { //saving start coordinates for mesh dragging startDraggir.gPoint = 3imple2Dto3D (viewport3d, pt) ;</td>
<td> 427. 428 .</td><td> _startDraggir.gMeshPoints = new Point3D[4]; Array.CcnstrainedCopy(_draggingPclygon.PointsTransformed, 0, _startDraggingMeshPoints, 0, 4);</td>
Date Reçue/Date Received 2021-11-12
<td> 423. 430. 431. 432. 433. 434. 435. 436. 437. 438 . 439. 440. 441. 442.</td><td> } } //Commence dragging operation. isDragging = true; CaptureMouse() ; //args.Handled = true; } protected override void OnMouseMove(MouseEventArgs args) base.OnMouseMove(args); //Determine if it is OK to move polygon or corner. if ((Readonly && _isDragging && _draggingPolygon != null && _renderedWisps.All(rw => !rw.ContentPolygonShown I I rw.Contentpolygon == draggingPolygon))</td>
<td> 443. 444. 445. 446. 447. 448 . 443.</td><td> { Point ptMouse = args.GetPosition(viewport3d); // Vertex dragging if ( draggingVertexlndex >= 0) { -draggingPolygon.PointsTransformed[_draggingVertexIndex] = Simple2Eto3D(viewport3d, ptMouse, -draggingPolygon.PointsTransformed[_draggingVertexIndex].2);</td>
<td> 450.</td><td> _draggingPolygon.Parent.CornerPoints[_draggingVertex!ndex] = Simple3Eto2D(viewport3d, draggingPolygon.PointsTransformed[ draggingVertexIndex]) ;</td>
<td> 451. 452. 453. 454. 455.</td><td> } II Mesh dragging else { Point3D curFosition = Simple2Dto3D(viewport3d, ptMouse);</td>
<td> 456.</td><td> vector3D offset = curFosition -StartDraggingPoint;</td>
<td> 457. 458 . 459. 460. 461.</td><td> offset.Z = 0; for (int i = 0; i < 4; i++) { -draggingPolygon.PointsTransformed[i] = -StartDraggingMeshPoints[i] + offset;</td>
<td> 462.</td><td> -draggingPolygon.Parent.CornerPoir.ts [i] = Simple3Eto2D(viewport3d, -draggingPolygon.PointsTransformed[i]) ;</td>
<td> 463. 464. 465. 466. 467.</td><td> } } //updating outline -draggingPolygon.Parent.UpdateOutline(-draggingPolygon.Outline);</td>
468 .
Date Reçue/Date Received 2021-11-12
<td> 469.</td><td> Canvas.SetLeft(-draggingPolygon.Control, (_draggingPolygon.Parent.CornerPoints[1].X + _draggingPolygon.Parent.CornerPoints[3].X draggingpolygon.Control.Actualwidth) * 0.5);</td>
<td> 470.</td><td> Canvas.SetTop( draggingPolygon. Control, Math.Max(_draggingPolygon.Parent.CornerPoints[1].Y, _draggingPolygon.Parent.CornerPoints[3]. Y));</td>
<td> 471. 472. 473.</td><td> //updating transformation matrix. _draggingPolygon.MatrixTransform.Matrix = CalculateNonAffineTransform(_draggingPolygon.PointsTransformed);</td>
<td> 474. 475. 476. 477. 478 .</td><td> //args.Handled = true; } protected override void OnMouseLeftButtonUp(MouseButtonEventArgs args)</td>
<td> 479. 480. 481. 482. 483. 484 . 485. 486.</td><td> base.OnMouseUp(args); if ( isDragging) { Point mousePoint = args.GetPosition(viewport3d); //if polygon was not moved and user clicked on a right one, showing content polygon</td>
<td> 487.</td><td> if (ShowCcntent && _draggingWisp != null && _draggingXisp.WispPolygon == _draggingPolygon &&</td>
<td> 488 .</td><td> Math.Abs(mousePoint.X - -StartDraggingMousePoint.X) < 2 S& Math.Abs(mousePoint.Y startDraggingMousePoint.Y) < 2)</td>
<td> 489. 490. 491. 492. 493. 494. 495. 496.</td><td> { if ( !_draggingWisp.ContentPolygonShown) { ShowContentPolygon(_draggingWisp); } else //or hiding content polygon if it was shown { //reverting conent polygon params, cause Save Content button was not pressed</td>
<td> 497.</td><td> _draggingWisp.ContentPolygcn. Parent = _draggingXisp. Parent.ContentPolygon = -draggingXisp.ContentPolygonBackup;</td>
<td> 498 . 499. 500. 501.</td><td> HideContentPolygon(_draggingWisp); } } //else it was a drag operation and it's needed to save values to xml.</td>
<td> 502. 503. 504. 505. 506. 507.</td><td> else if (!Readonly ! isDraggingContent) { SaveData() ; } _isDragging = false;</td>
Date Reçue/Date Received 2021-11-12
<td> 508 . 509. 510. 511. 512. 513. 514.</td><td> _isDraggingConter.t = false; ReleaseMouseCapture(); //args.Handled = true; } private RayMeshGecmetry3DHitTestResult GetMeshAtPoint(Point point)</td>
<td> 515. 516. 517. 518. 519. 520. 521. 522.</td><td> RayMeshGeometry3DHitTestResult resultMesh = null; !/ Obtain the Visual3D objects under the mouse pointer. VisualTreeHelper.Hitlest(viewport3d, null, new HitTestResultCallback((hitTestResult) => { resultMesh = hitTestResult as RayMeshGeometry3DHitTestResult;</td>
<td> 523. 524.</td><td> //which is not an invisible content polygon or something else</td>
<td> 525.</td><td> if (resultMesh == null || (resultMesh.VisualHit as ModelVisual3D) == null ||</td>
<td> 526.</td><td> Array.IndexOf(_renderedWisps.Select(rw => rw.WispFolygon.Mesh).ToArray(), resultMesh.MeshHit) < 0 &S</td>
<td> 527.</td><td> Array.IndexOf(_renderedwisps.Where(rw => rw.ContentPolygonShown).Select(rw => rw.Contentpolygon.Mesh).TcArrayO, resultMesh.MeshHit) < 0 &&</td>
<td> 528 .</td><td> Array.IndexOf(_renderedDefaultPolygons.Select(rdp => rdp.Mesh).ToArray(), resultMesh.MeshHit) < 0)</td>
<td> 529. 530. 531. 532. 533. 534. 535. 536. 537. 538 . 539. 540. 541. 542. 543. 544. 545. 546. 547.</td><td> { resultMesh = null; return HitTestResultBehavior.Continue; } return HitTestResultBehavior.Stop; }), new PointHitTestParameters(point) ); return resultMesh; } private void ShowContentFolygon(RenderedWisp renderedWisp) if (renderedWisp.ContentFolygonShown) return; var cp = (renderedWisp.Contentpolygon.Parent as Contentpolygon);</td>
<td> 548 .</td><td> var wp = (renderedWisp.wispPolygon.Parent as WispPolygon);</td>
<td> 549. 550.</td><td> //determining clicking group and click availability</td>
Date Reçue/Date Received 2021-11-12
<td> 551. 552. 553. 554. 555. 556. 557. 558 . 559. 560. 561. 562. 563. 564. 565. 566.</td><td> if ( ! string.IsNullOrEmpty(wp.ClickGroup)) { if ( clickedGroups.Contains(wp.ClickGroup) ) { return; } else { _clickedGroups.Add(wp.ClickGroup); } } //playing sound if (PlaySound && ! string.IsNullOrEmpty(wp.Clicksound)) { renderedWisp.MediaPlayer.Open(new Uri(wp.Clicksound, UriKind.Relative)) ;</td>
<td> 567. 568 . 569. 570. 571. 572. 573. 574.</td><td> renderedWisp.MediaPlayer.Volume = 1; renderedWisp.MediaPlayer. Play () ; } //hiding default polygons if (Readonly) { var defaultPolygonlds = renderedWisp. Parent.ShowHideDefaultPolygons;</td>
<td> 575.</td><td> var renderedDefaultPolygons = _renderedDefaultPolygons;</td>
<td> 576. 577. 578 . 579. 580.</td><td> if (defaultPolygonlds != null) { foreach (var id in defaultPolygonlds) { var rdp = renderedDefaultPolygons.FirstOrDefault(p => p.ID == id);</td>
<td> 581. 582. 583.</td><td> if (rdp != null) { //increasing its hide count (0 visible, 1 and more - invisible)</td>
<td> 584.</td><td> rdp.EideCount = Math.Max(l, rdp.HideCount + 1);</td>
<td> 585.</td><td> rdp.Material.Brush = Brushes.Transparent;</td>
<td> 586. 587. 588 .</td><td> if (ShowOutlines) { rdp.OutlinePath.Stroke = Brushes.Transparent;</td>
<td> 589.</td><td> rdp.Control.Visibility = Visibility.Hidden;</td>
<td> 590. 591. 592. 593. 594. 595.</td><td> } } } }</td>
Date Reçue/Date Received 2021-11-12
<td> 596. 597. 598 . 599. 600. 601. 602. 603. 604. 605. 606. 607. 608 . 609. 610. 611.</td><td> //backuping content polygon renderedWisp.ContentPolygonBackup = new ContentPolygon() { Content = cp.Content, Contentorientation = cp.Contentorientation, ContentType = cp.ContentType, CornerPoints = new Pointcollection(cp.Corr.erPoints), FrameRate = cp.FrameRate, Loop = cp.Loop, Timeout = cp.Timeout, ZOrder = cp.ZOrder }; //changing wisp polygon content to click content wp.ResetClickBrush() ; renderedWisp.WispPolygon.Material. Brush = wp.ClickContentBrush;</td>
<td> 612. 613. 614.</td><td> //updating content polygon position UpdateCornerPointPositions(cp, renderedWisp.ContentPolygon.MatrixTransform);</td>
<td> 615. 616. 617. 618. 619.</td><td> for (int i = 0; i < 4; i++) { //preserve z order renderedWisp.ContentPolygon.Mesh.Positions[i] = new Point3D(renderedWisp.ContentPolygon.Mesh.Positions[i].X, renderedWisp.ContentPolygon.Mesh.Positions[i]. Y, ZIncrement);</td>
<td> 620. 621. 622.</td><td> } //Changing it's visibility (material, outline and controls)</td>
<td> 623.</td><td> renderedWisp.ContentPolygon.Material. Brush = cp.ContentBrush;</td>
<td> 624. 625. 626.</td><td> if (ShowOutlines) { cp.Updateûutline(renderedWisp.ContentPolygon.Outline);</td>
<td> 627.</td><td> renderedWisp.ContentPolygon.OutlinePath.Stroke = (SolidCclorBrush)(new Brushconverter ().ConvertFrom(#00aff0)) ;</td>
<td> 628 . 629. 630.</td><td> var panel = renderedWisp.ContentPolygon.Control; panel.Visibility = Visibility.Visible; Canvas.SetLeft(panel, (cp.CornerPoints[1].X + cp.Cornerpoints[3].X - panel.Actualwidth) * 0.5);</td>
<td> 631.</td><td> Canvas.SetTop(panel, Math.Max(cp.CornerPoints[1].Y, cp.CornerPoints[3].Y)) ;</td>
<td> 632. 633. 634. 635.</td><td> } else if (cp.Timeout > 0) { renderedWisp.HideContentPolygonTimer.Interval = Timespan.FromSeconds(cp.Timeout);</td>
<td> 636. 637. 638 .</td><td> renderedWisp.HideContentPolygonTimer.Start () ; }</td>
Date Reçue/Date Received 2021-11-12
<td> 639. 640. 641. 642. 643. 644. 645. 646. 647. 648 .</td><td> renderedWisp.ContentPolvgonShown = true; ) private void HideContentPolygon(RenderedWisp renderedWisp) renderedWisp.HideContentPolygonTimer.Stop(); if (renderedWisp.ContentPolygonShown) { var wp = (renderedWisp.WispPolygon.Parent as WispPolygon);</td>
<td> 649. 650. 651. 652. 653. 654. 655. 656.</td><td> //determining clicking group and relesing it if ( ! string.IsNullOrEmpty(wp.ClickGroup)) { clickedGroups.Remove(wp.ClickGroup); } //showing default polygons which were not hide by other polygons</td>
<td> 657. 658 . 659.</td><td> if (Readonly) { var defaultPolygonlds = renderedWisp.Parent.ShowHideDefaultPolygons;</td>
<td> 660.</td><td> var renderedDefaultPolygons = _renderedDefaultPolygons;</td>
<td> 661. 662. 663. 664. 665.</td><td> if (defaultPolygonlds ! = null) ( foreach (var id in defaultPolygonlds) { var rdp = renderedDefaultPolygons.FirstOrCefault(p => p.ID == id);</td>
<td> 666. 667. 668 .</td><td> if (rdp != null) { //decreasing its hide count (C visible, 1 and more - invisible)</td>
<td> 669. 670. 671. 672. 673.</td><td> rdp.Hidecount--; if (rdp.HideCount <= 0) { rdp.HideCount = 0; rdp.Material.Brush = rdp. Parent.ContentBrush;</td>
<td> 674. 675. 676.</td><td> if (ShowOutlines) { rdp.OutlinePath.Stroke = (SolidCclorBrush)(new Brushconverter ().ConvertFrom(#00aff0)) ;</td>
<td> 677.</td><td> rdp.Control.Visibility = Visibility.Visible;</td>
<td> 678 . 679. 680. 681. 682. 683.</td><td> } } } } } }</td>
Date Reçue/Date Received 2021-11-12
684.
685.
686.
687.
688 .
689.
690.
691.
692.
693.
694.
695.
696.
697.
698 .
699.
700.
701.
702.
703.
704.
705.
706.
707.
708 .
709.
710.
711.
712.
713.
714.
715.
716.
717.
718.
719.
720.
721.
722.
723.
//changing wisp polygon content to regular content wp.ResetBrush();
renderedWisp.WispPolygon.Material. Brush = wp.ContentBrush;
//updating content polygon position to behind camera position renderedWisp.ContentPolygon. Parent.ResetBrush( ) ;
for (int i = 0; i < 4; i++) { renderedWisp.ContentPolygon.Mesh.Positions[i] new Point3D(renderedWisp.ContentPolygon.Mesh.Positions[i].X, renderedWisp.ContentPolygon.Mesh.Positions[i].Y, 100);
} //hiding it (marerial, outline and control) renderedWisp.ContentPolygon.Material. Brush =
Brushes.Transparent;
if (Showoutlines) { renderedWisp.ContentPolygon.OutlinePath. Stroke = Brushes.Transparent;
renderedWisp.ContentPolygon.Control.Visibility = Visibility.Hidden;
} renderedWisp.ContentPolygonShown = false; } private void OnNonAffineTransformControlSizeChanged(object sender, SizeChangedEventArgs e) k if (e.PreviousSize.Width > 0) { var oldwidth = ifiaincanera. width;
mainCamera. Width = mainCamera.Width *
e.Newsize.Width / e.PreviousSize.Width;
mainCamera.Position = new Point3D( mainCamera.Position.X + 0.5 * (mainCamera.Width
- oldWidth), // - newPosition.X + oidPosition.X, mainCamera.Position.Y * 0.5 * (e.PreviousSize.Height - e.NewSize.Height) * mainCamera.Width / viewport3d.Actualwidth, mainCamera. Position.Z );
} }
private void OnNonAffinelransformControlLoaded(object sender, RoutedEventArgs e)
Date Reçue/Date Received 2021-11-12
<td> 724.</td><td> overlay.Visibility = ShowOutlines ? Visibility.Visible : Visibility.Hidden;</td>
<td> 725. 726. 727. 728 . 729. 730. 731. 732. 733. 734. 735. 736. 737. 738 . 739. 740. 741. 742.</td><td> if (Visibility == System.Windows.Visibility.Visible) { LoadData() ; Initialize (); } } private void Initialize() viewport3d.Children.Clear (); overlay.Children.Clear (); var wisps = Wisps; var defaultpolygons = Defaultpolygons; if (wisps == null) return;</td>
<td> 743. 744. 745.</td><td> var modelVisual3D = new ModelVisual3D() ; var model3DGroup = new Model3DGroup(); //for each provided brush one plane is created, each next plane is a little further (first on is the most visible)</td>
<td> 746. 747. 748 . 749. 750.</td><td> var models = new List<GeometryModel3D>(); var wispsCount = wisps.Length; var count = defaultpolygons != null ? defaultFolygons.Length : 0;</td>
751.
<td> 752. 753.</td><td> #region Default polygons initialization _renderedDefaultPolygons = new RenderedDefaultPolygon[count];</td>
<td> 754. 755. 756. 757.</td><td> for (int i = 0; i < count; i++) { double z = i < count ? ((defaultpolygons[i].ZOrder > 0 ? defaultFolygons[i].ZOrder : i) + wispsCount + 1) * ZIncrement :</td>
<td> 758 . 759.</td><td> ZIncrement; //double z = (zCrder != null && zOrder.Length > i) ? zOrder[i] * ZIncrement : i * ZIncrement;</td>
<td> 760. 761.</td><td> _renderedDefaultFolygons[i] = new RenderedDefaultPolygon()</td>
<td> 762. 763. 764. 765. 766. 767. 768 . 769. 770.</td><td> { Parent = defaultpolygons[i], PointsTransformed = new Point3D[4], ID = defaultFolygons[i].ID }; var pointsTransformed = new Point3D[] { new Point3D(0, 0, z), new Point3D(0, 1, z),</td>
Date Reçue/Date Received 2021-11-12
771. new Point3D(l, 0, z),
772. new Point3D(l, 1, z)
773. };
<td> 774. 775.</td><td> renderedDefaultPolygons[i].Mesh = new MeshGèôttètry3D()</td>
<td> 776. 777. 778 .</td><td> { //initial positions of planes Positions = new Point3DCollection(pointsTransformed),</td>
<td> 779.</td><td> TextureCoordinates = new Pointcollection(new Point[] {</td>
<td> 780. 781. 782. 783. 784. 785.</td><td> new Point(0, 0), new Point(0, 1), new Point(1, 0), new Point(1, 1) } ), Trianglelndices = new Int32Collection(new Int32[] {</td>
<td> 786. 787. 788 . 789.</td><td> 0, 2, 1, 2, 3, 1 }) }; _renderedDefaultPolygons[i].MatrixTransform = new MatrixTransform3D();</td>
<td> 790. 791. 792. 793.</td><td> if (Showcontent) { //creating brush _renderedDefaultpolygons[i].Material = new Diffuseraterial(defaultpolygons[i]. ContentBrush);</td>
<td> 794. 795. 796. 797.</td><td> } else { _renderedDefaultPolygons[i].Material = new DiffuseMaterial(Brushes.Transparent);</td>
<td> 798 . 799. 800 . 801. 802. 803.</td><td> } if (Showoutlines) { //creating outline _renderedDefaultpolygons[i].Outline = defaultpolygons[i].CreateOutline();</td>
<td> 804. 805. 806. 807. 808 .</td><td> //adding to outlines collections overlay.Children.Add(new Path() { Stroke = (SolidColorBrush)(new Brushconverter () .ConvertFroitiC’ttOOaffO”) ),</td>
<td> 809. 810. 811. 812.</td><td> StrokeThickness = 2, Data = new PathGeometry() { Figures = new PathFigureCollection(new PathFiguref] {</td>
<td> 813.</td><td> _renderedDefaultPolygons[i].Outline</td>
Date Reçue/Date Received 2021-11-12
<td> 814.</td><td> })</td>
<td> 815.</td><td> }</td>
<td> 816.</td><td> });</td>
<td> 817.</td><td></td>
<td> 818.</td><td> var name = new TextBlock()</td>
<td> 819.</td><td> {</td>
<td> 820.</td><td> Text = defaultpolygons[i]. ID,</td>
<td> 821.</td><td> TextAligrment = TextAlignment.Center,</td>
<td> 822.</td><td> Foreground = (SolidColorBrush)(new</td>
<td></td><td> Brushconverter ().ConvertFrom(”#00aff0) ),</td>
<td> 823.</td><td> };</td>
<td> 824.</td><td> _renderedDefaultPolygons[i].Control = name</td>
<td> 825.</td><td></td>
<td> 826.</td><td> overlay.Children.Add(name);</td>
<td> 827.</td><td> var polygon = defaultpolygons[i];</td>
<td> 828 .</td><td> name.Loaded += new RoutedEventHandler((s, .</td>
<td></td><td> =></td>
<td> 829.</td><td> {</td>
<td> 830 .</td><td> Canvas.SetLeft(name,</td>
<td></td><td> (polygon.CornerPoints[1].X + polygon.Cornerpoints[3].X name.Actualwidth) <sup>+</sup> 0.5);</td>
<td> 831.</td><td> Canvas.SetTop(name,</td>
<td></td><td> Math.Max(polygon.CornerPoints[1].Y, polygon.CornerPoints[3].Y)</td>
<td> 832.</td><td> });</td>
<td> 833 .</td><td> }</td>
<td> 834.</td><td> modeIs.Add (</td>
<td> 835.</td><td> new GeometryModel3D()</td>
<td> 836.</td><td> {</td>
<td> 837.</td><td> Geometry = _renderedDefaultPolygor.s [i]</td>
<td> 838 .</td><td> Material =</td>
<td></td><td> _renderedDefaultPolygons[i].Material,</td>
<td> 839.</td><td> Transform =</td>
<td></td><td> _renderedDefaultPolygons[i].MatrixTransform</td>
<td> 840.</td><td> }</td>
<td> 841.</td><td> );</td>
<td> 842.</td><td> }</td>
<td> 843.</td><td> #endregion</td>
<td> 844.</td><td></td>
<td> 845.</td><td> #region Wisps initialization</td>
<td> 846.</td><td> _renderedWisps = new RenderedWisp[wispsCount];</td>
<td> 847.</td><td> for (int i = 0; i < wispsCount; i++)</td>
<td> 848 .</td><td> {</td>
<td> 849.</td><td> double z = i < wispsCount ?</td>
<td> 850.</td><td> (((wisps[i].WispPolygon.ZOrder > 0) ?</td>
<td></td><td> wisps[i].WispPolygon.ZOrder : i) + 1) * ZIncrement :</td>
<td> 851.</td><td> ZIncrement;</td>
<td> 852.</td><td> //double z = (zOrder ! = null && zOrder.Length</td>
<td></td><td> zOrder[i] * ZIncrement : i * ZIncrement;</td>
<td> 853.</td><td></td>
<td> 854.</td><td> var timer = new DispatcherTimer();</td>
<td> 855.</td><td> timer.Tick += OnEideContentPolygonTimerTick;</td>
<td> 856.</td><td></td>
<td> 857.</td><td> _renderedwisps[i] = new RenderedWisp()</td>
<td> 858 .</td><td> {</td>
args) .Mesh,
Date Reçue/Date Received 2021-1 ^<sub>STnvrE SHEET</sub> (RULE 26)
<td> 859. 860. 861. 862. 863. 864. 865. 866. 867. 868 . 869. 870. 871. 872. 873. 874. 875. 876. 877. 878 . 879. 880 . 881. 882 . 883 .</td><td> HideCcntentFolygonTimer = timer, MediaPlayer = new MediaPlayer(), Parent = wisps[i], WispPolygon = new RenderedPolygon() { Parent = wisps[i].WispPolygon, PcintsTransformed = new Point3D[4] }, ContentPolygon = new RenderedPolygon() { Parent = wisps[i].ContentPolygon, PcintsTransformed - new Point3D[4] } }; timer.Tag = _renderedWisps[i]; var pointsTransformed = new Point3D[] { new Point3D(0, 0, z), new Point3D(0, 1, z), new Point3D(l, 0, z) , new Point3D(l, 1, z) ); _renderedwisps[i].WispPolygon.Mesh = new MeshGeometry3D()</td>
<td> 884. 885. 886.</td><td> { //initial positions of planes Positions = new Point3DCollection(pointsTransformed),</td>
<td> 887 .</td><td> TextureCoordinates = new Pointcollection(new Point[] {</td>
<td> 888 . 889. 890. 891. 892. 893.</td><td> new Point(0, 0), new Point (0, 1), new Point(1, 0), new Point(1, 1) }), Trianglelndices = new Int32Collection(new Int32[] {</td>
<td> 894. 895. 896. 897.</td><td> 0, 2, 1, 2, 3, 1 }) }; _renderedWisps[i].WispPolygon.MatrixTransform = new MatrixTransform3D();</td>
<td> 898 . 899. 900. 901.</td><td> if (ShowContent) { //creating brush _renderedWisps[i].WispPolygon.Material = new Diffuseraterial(wisps[i].WispPolygon.ContentBrush);</td>
<td> 902. 903. 904. 905.</td><td> } else { _renderedwisps[i].WispPolygon.Material = new DiffuseMaterial(Brushes.Transparent) ;</td>
Date Reçue/Date Received 2021-11-12
<td> 906. 907. 908 . 909. 910. 911.</td><td> } if (ShowOutlines) { //creating outline _renderedwisps[i].WispPolygon.Outline = wisps[i].WispPolygon.CreateOutline();</td>
<td> 912. 913. 914. 915. 916.</td><td> //adding to outlines collections overlay.Children.Add(new Path() { Stroke = (SolidColorBrush)(new BrushConverter().ConvertFrom(#00aff0<sup>n</sup>) ),</td>
<td> 917. 918. 919. 920.</td><td> StrokeThickness = 2, Data = new PathGeometry() { Figures = new PathFigureCollection(new PathFigure[] {</td>
<td> 921.</td><td> _renderedWisps[i].WispPolygon.Outline</td>
<td> 922. 923. 924. 925. 926. 927. 928 . 929. 930.</td><td> }) } }); var name = new TextBlock() { Text = wisps[i].Name, TextAligrrnent = TextAlignment.Center, Foreground = (SolidColorBrush)(new Brushconverter ().ConvertFrom(#00aff0)),</td>
<td> 931. 932. 933. 934. 935. 936.</td><td> }; _renderedWisps[i].WispPolygon.Control = name; overlay.Children.Add(name); var polygon = wisps[i].WispPolygon; name.Loaded += new RoutedEventHandler((s, args) _X</td>
<td> 937. 938 .</td><td> —Λ { Canvas.SetLeft(name, (polygon.CornerPoints[1].X + polygon.Cornerpoints[3].X name.Actualwidth) * 0.5);</td>
<td> 939.</td><td> Canvas.SetTop(name, Math.Max(polygon.CornerPoints[1].Y, polygon.CornerPoints[3].Y)) ;</td>
<td> 940. 941. 942. 943. 944. 945.</td><td> }); } modeIs.Add ( new GeometryModel3D() { Geometry = _renderedWisps[i].WispPolygon.Mesh,</td>
<td> 946.</td><td> Material = _renderedXisps[i].WispPolygon.Material,</td>
<td> 947.</td><td> Transform = _renderedXisps[i].WispPolygon.MatrixTransform</td>
Date Reçue/Date Received 2021-11-12
<td> 948 . 949. 950. 951.</td><td> } ); renderedWisps[i].ContentPolygon.Mesh = new MeshGeorr.etry3D ( )</td>
<td> 952. 953. 954.</td><td> { //initial petitions of planes Positions = new Point3DCollection(pointsTransformed),</td>
<td> 955.</td><td> Texturecoordinates = new Pointcollection(new Point[] {</td>
<td> 956. 957. 958 . 959. 960. 961.</td><td> new Point(0, 0), new Point(0, 1), new Point (1, 0), new Point (1, 1) }), Trianglelndices = new Int32Collection(new Int32[] {</td>
<td> 962. 963. 964. 965.</td><td> 0, 2, 1, 2, 3, 1 }) }; _renderedWisps[i].ContentPolygon.MatrixTransform = new MatrixTransform3D();</td>
<td> 966. 967.</td><td> _renderedKisps[i].ContentPolygon.Material = new DiffuseMaterial(Brushes.Transparent);</td>
<td> 968 . 969. 970. 971.</td><td> if (Showoutlines) { _renderedWisps[i].ContentPolygon.Outline = Polygon.CreateEmptyOutline();</td>
<td> 972.</td><td> _renderedWisps[i].ContentPolygon.OutlinePath = new Path ()</td>
<td> 973. 974. 975. 976. 977. 978 .</td><td> { Stroke = Brushes.Transparent, StrokeThickness = 2, Data = new PathGeometry() { Figures = new PathFigureCollection(new PathFigure[] {</td>
<td> 979.</td><td> _renderedWisps[i].ContentPolygon.Outline</td>
<td> 980. 981. 982. 983.</td><td> }) } }; overlay.Children.Add(_renderedWisps;i].ContentPolygon.OutlinePath) ;</td>
<td> 984. 985. 986. 987. 988 . 989. 990.</td><td> //container for controls var panel = r.ew StackPanel() Visibility = Visibility.Hidden, Orientation = Orientation.Horizontal };</td>
Date Reçue/Date Received 2021-11-12
<td> 991. 992. 993. 994. 995. 996. 997. 998 . 999. 1000. 1001.</td><td> //Save Content button var button = new Button () { Content = Save Content, Margin = new Thickness(10) }; button.Click += OnSaveContentButtonClick; button.Tag = _renderedWisps[i]; panel.Children.Add(button);</td>
<td> 1002. 1003. 1004. 1005.</td><td> //Rotate image var image = new Inage () { Source = new Bitmapimage(new</td>
Uri (/rotate.png, UriKind.Relative) ),
<td> 1006. 1007. 1008. 1009. 1010. 1011. 1012. 1013.</td><td> Margin = new Thickness(0, 10, 0, 10), Width = 20, Height = 20 }; image.MouseUp += OnRotateContentButtor.Click; image.Tag = _renderedWisps[i]; //nice antializings RenderOptions.SetBitmapScalingMode(image,</td>
BitmapScalingMode.Fant);
<td> 1014. 1015. 1016. panel;</td><td> panel.Children.Add(image); overlay.Chilcren.Add(panel); _renderedWisps[i].Contentpolygon.Control =</td>
<td> 1017. 1018.</td><td> }</td>
<td> 1019. 1020. 1021. 1022.</td><td> modeIs.Add ( new GeometryModel3D() { Geometry =</td>
renderedWisps[i].ContentPolygon.Mesh,
1023. Material = _renderedKisps[i].ContentPolygon.Material,
1024. Transform = renderedWisps[i]. ContentPolygon.MatrixTransform
1025. }
<td> 1026. 1027. 1028. 1029. 1030. 1031. 1032. 1033. 1034.</td><td> ); } #endregion _loaded = true; UpdateCornerPointPositions(); //storing models in correct z-order models.Sort(new Comparison<GeonetryModel3D>((a, b) =></td>
a.Geometry.Bounds.Z.CompareTo(b.Geometry.Bounds.Z)) ) ;
<td> 1035. 1036.</td><td> models.ForEach(o => mode!3DGroup.Children.Add(o)) ; model3DGroup.Children.Add(new</td>
AmbientLight(Colors.White)) ;
Date Reçue/Date Received 2021-11-12
<td> 1037. 1038. 1039.</td><td> modelVisual3D.Content = mode!3DGroup; this.viewport3d.Children.Add(modelVisual3D); }</td>
<td> 1040. 1041.</td><td> private void OnSaveContentButtonClick(object sender, RoutedEventArgs e)</td>
<td> 1042. 1043. 1044. 1045. 1046. 1047. 1048. 1049.</td><td> var fe = (sender as FrameworkElement); if (fe == null) return; var rw - fe.Tag as RenderedWisp; if (rw == null) return;</td>
<td> 1050. 1051. 1052. 1053. 1054. 1055. 1056. 1057. 1058. 1059. 1060.</td><td> SaveData ( ) ; HideContentPolygon(rw); ) III <summary> III Loads data from provided xml file. Ill </summary> private void LoadDataO { if ( ! string.isNullOrEmpty(StorageFile) && System.IO.File.Exists(StorageFile))</td>
<td> 1061. 1062. 1063.</td><td> ( try {</td>
<td> 1064.</td><td> using (var fs = System.10.File.OpenRead(StorageFile))</td>
<td> 1065. 1066.</td><td> { XmlSerializer xs = new XmlSerializer(typeof(Objectstorage) , new Type[] {</td>
<td> 1067. 1068. 1069. 1070. 1071. 1072. 1073. 1074. 1075.</td><td> typeof(Wisp[]), typeof(Wisp), typeof(CententPolygon), typeof (WispPolygor.), typeof(Polygon), typeof(Defaultpolygon[]) typeof(DefaultPolygon) )); var objectstorage = (Objectstorage)xs.Deserialize(fs);</td>
<td> 1076. 1077. 1078.</td><td> _internalChange = true; Wisps = objectstorage.Wisps; DefaultFolygons objectstorage. DefaultPolygons ;</td>
<td> 1079. 1080. 1081. 1082. 1083. 1084.</td><td> internalchange = false; } ) catch { } } )</td>
Date Reçue/Date Received 2021-11-12
<td> 1085.</td><td></td>
<td> 1086.</td><td> Ill <summary></td>
<td> 1087.</td><td> III Saves data to provided xml file.</td>
<td> 1088.</td><td> Ill </summary></td>
<td> 1089.</td><td> private void SaveData()</td>
<td> 1090.</td><td> {</td>
<td> 1091.</td><td> if ( ! string.IsNullOrEmpty(StorageFile) && Wisps ! = null)</td>
<td> 1092.</td><td> {</td>
<td> 1093.</td><td> using (var fs = System.IO.File.Create(StorageFile))</td>
<td> 1094.</td><td> {</td>
<td> 1095.</td><td> XmlSerializer xs = new</td>
<td></td><td> XmlSerializer(typeof(Objectstorage), new Type[] {</td>
<td> 1096.</td><td> typeof(Wisp[]I,</td>
<td> 1097.</td><td> typeof(Wisp),</td>
<td> 1098.</td><td> typeof(ContentPolygon),</td>
<td> 1099.</td><td> typeof(WispPolygon),</td>
<td> 1100.</td><td> typeof(Polygon),</td>
<td> 1101.</td><td> typeof(Defaultpolygon []),</td>
<td> 1102.</td><td> typeof(Defaultpolygon)</td>
<td> 1103.</td><td> });</td>
<td> 1104.</td><td> var objectstorage = new Objectstorage ()</td>
<td> 1105.</td><td> {</td>
<td> 1106.</td><td> Wisps = this.Wisps,</td>
<td> 1107.</td><td> Defaultpolygons = this.DefaultPolygons</td>
<td> 1108.</td><td> };</td>
<td> 1109.</td><td> xs.Serialize(fs, objectstorage);</td>
<td> 1110.</td><td></td>
<td> 1111.</td><td> fs.Close ();</td>
<td> 1112.</td><td> }</td>
<td> 1113.</td><td> }</td>
<td> 1114.</td><td> }</td>
<td> 1115.</td><td></td>
<td> 1116.</td><td> III <summary></td>
<td> 1117.</td><td> III Rotates content of Content polygon</td>
<td> 1118.</td><td> III </summary></td>
<td> 1119.</td><td> Hi <param name=sender></param></td>
<td> 1120.</td><td> III <param name=<sup>n</sup>ex/param></td>
<td> 1121.</td><td> private void OnRotateContentButtonClick(object sender,</td>
<td></td><td> MouseButtonEventArgs e)</td>
<td> 1122.</td><td> {</td>
<td> 1123.</td><td> var fe = (sender as FrameworkElement);</td>
<td> 1124.</td><td> if (fe == null)</td>
<td> 1125.</td><td> return;</td>
<td> 1126.</td><td></td>
<td> 1127.</td><td> var rw = fe.Tag as RenderedWisp;</td>
<td> 1128.</td><td> if (rw == null)</td>
<td> 1129.</td><td> return;</td>
<td> 1130.</td><td></td>
<td> 1131.</td><td> rw.Parent.ContentPolygon.Contentorientation -= 90;</td>
<td> 1132.</td><td> if (rw.Parent.ContentPolygon.ContentOrientation < 0)</td>
<td> 1133.</td><td> {</td>
<td> 1134.</td><td> rw.Parent.ContentPolygon.ContentOrientation += 360;</td>
<td> 1135.</td><td> }</td>
<td> 1136.</td><td></td>
100
Date Reçue/Date Received 2021-11-12
<td> 1137.</td><td> rw.Contentpolygon.Material. Brush =</td>
<td></td><td> rw.ContentPolygon.Parent.ContentBrush;</td>
<td> 1138. 1139. 1140. 1141.</td><td> } III <summary> III Updates transformations matrices according new corner points positions</td>
<td> 1142. 1143. 1144. 1145. 1146. 1147. 1148. 1149. 1150. 1151. 1152. 1153. 1154.</td><td> III </summary> private void UpdateCornerPointPositions() { if (!_loaded) return; //var count = Brushes.Length; var wisps = Wisps; var defaultpolygons = Defaultpolygons; if (wisps == null) return;</td>
<td> 1155. 1156.</td><td> var count = wisps.Length; //for each provided brush one plane is created, each next plane is a little further (first on is the most visible)</td>
<td> 1157. 1158. 1159.</td><td> for (int i = 0; i < count; i++) { UpdateCornerPointPositions(wisps[i].WispPolygon, rendered'Wisps[i].WispPolygon.MatrixTransform, i * Zlncrement);</td>
<td> 1160. 1161. 1162. 1163. 1164. 1165. 1166. 1167.</td><td> } if (defaultpolygons != null) { var dpCount = defaultpolygons.Length; for (int i = 0; i < dpCount; i++) { UpdateCornerPointPositions(defaultpolygons[i] renderedDefaultPolygons[i].MatrixTransform, (count + i) * Zlncrement);</td>
<td> 1168. 1169. 1170. 1171. 1172.</td><td> } } } private void UpdateCornerPointPositions(Polygon polygon, MatrixTransform3D matrix, double defaultZ = Zlncrement)</td>
<td> 1173. 1174.</td><td> double z = (polygon.ZOrder > 0) ? polygon.ZOrder * Zlncrement : defaultZ;</td>
<td> 1175. 1176. 1177. 1178. 1179. 1180. 1181. 1182.</td><td> var pointsTransformec = new Point3D[] { new Point3D(0, 0, z), new Point3D(0, 1, z), new Point3D(l, 0, z), new Point3D(l, 1, z) for (int j = 0; j < 4; j++)</td>
101
Date Reçue/Date Received 2021-11-12
<td> 1183. 1184.</td><td> { //transforming from display to 3d coordinates or using default values</td>
<td> 1185.</td><td> var inputCornerPointRelative = [polygon.CornerPoints != null && polygon.CornerPoints.Count > j) ?</td>
<td> 1186.</td><td> Simple2Dto3E(viewport3d, polygon.CornerPoints[j]) : DefaultCornerPoints[j];</td>
<td> 1187. 1188.</td><td> for (int k = 0; k < 4; k++) {</td>
<td> 1189.</td><td> //it's needed to prevent NaN in matrix calculations (two points cannot have the same coordinates)</td>
<td> 1190.</td><td> if (j != k Î& Math.Abs(pointsTransformed[k].X inputCornerPointRelative.X) < 0.0001</td>
<td> 1191.</td><td> && Math.Abs(pointsTransformed[k]. Y inputCornerPointRelative,Y) < 0.0001)</td>
<td> 1192. 1193.</td><td> { inputCornerPointRelative.X = pointsTransformed[k].X + 0.0001;</td>
<td> 1194.</td><td> inputCorrerPointRelative.Y = pointsTransformed[k].Y + 0.0001;</td>
<td> 1195. 1196. 1197. 1198. 1199.</td><td> } } pointsTransformed[j[.X = inputCornerPointRelative.X; pointsTransformed[j].Y = inputCornerPointRelative.Y;</td>
<td> 1200. 1201. 1202.</td><td> } //updating matrix matrix.Matrix = CalculateNonAffineTransform(pointsTransformed);</td>
<td> 1203.</td><td> //updating corner point positons (in case of incomplete set provided)</td>
<td> 1204. 1205. 1206. 1207.</td><td> var outputcornerPoints = new Point[4]; for (int j = 0; j < 4; j++) ( outputCornerPoints[j] = Simple3Dto2D(viewport3d, pointsTransformed[j]);// new Point( pointsTransformed[i][j].X, _point$Tran$forraed[i][j],Y);</td>
<td> 1208. 1209. 1210. 1211.</td><td> ) _internalChange = true; polygon.CornerPoints = new Pointcollection(outputCornerPoints);</td>
<td> 1212. 1213. 1214.</td><td> internalchange = false; )</td>
<td> 1215. 1216. 1217. 1218. 1219. 1220.</td><td> II The input array of points describes a 2D rectangle II (with Z assumed to be zero) in the order II lower-left, upper-left, lower-right, upper-right. II The returned transform maps the points (0, 0, C), II (0, 1, 0), (1, 0, 0), and (1, 1, 0) to these points. private Matrix3D CalculateNonAffineTransform(Point3D[] points)</td>
<td> 1221. 1222.</td><td> r II Affine transform</td>
102
Date Reçue/Date Received 2021-11-12
<td> 1223. 1224. 1225. 1226. 1227. 1228. 1229. 1230. 1231. 1232. 1233. 1234. 1235. 1236. 1237. 1238. 1239. 1240. 1241. 1242. 1243. 1244. 1245. 1246. 1247. 1248. 1249. 1250. 1251. 1252. 1253. 1254. 1255. 1256. 1257. 1258. 1259. 1260. 1261. 1262. 1263. 1264.</td><td> H---------------- II This matrix maps (0, 0) —> ixO, yO) H (0, 1) —> (xl, yl) // (1, 0) --> (x2, y2) H (1, 1) —> (x2 + xl + xû, y2 + yl + yO) Matrix3D A = new Matrix3D(); A.Mil = points[2].X - points[0].X; A.M12 = points[2].Y - points[0].Y; À.M21 = points[l].X - points[0].X; A.M22 = points[l].Y - points[0].Y; A.OffsetX - points[0].X; A.OffsetY = points[0].Y; // Calculate point (a, b) that get mapped by the affine transform to (x3, y3) double den = A.Mil * A.M22 - A.M12 * A.M21; double a = (A.M22 * points[3].X - A.M21 * poir.ts[3].Y + A.M21 * A.OffsetY - A.M22 * A.OffsetX) / den; double b = (A.Mil * points[3].Y - A.M12 * poir.ts[3].X + A.M12 * A.OffsetX - A.Mil * A.OffsetY) / den; // Non-affine transform u-------------------- // This matrix maps (0, 0) --> (0, 0) II (0, 1) -> (0, 1) H (1, 0) -> (1, 0) // (1, 1) -> (a, b) Matrix3D B = new Matrix3D(); B.M11 - a / (a + b - 1) ; B.M22 = b / (a + b - 1) ; B.M14 = B.M11 - 1; B.M24 = B.M22 - 1; return B * A; } II The following two methods only work with OrthographicCamera, II with LookDirection of (0, 0, -1) and UpDirection of (0, 1, 0). II More advanced conversion routines can be found in the II Petzold.Media3D library.</td>
<td> 1265. 1266. 1267. 1268.</td><td> // Converts a 2D point in device-independent coordinates relative II to viewport3D to 3d space. private Point3D Simple2Eto3D(Viewport3D vp, Point pt, double z = 0.0)</td>
103
Date Reçue/Date Received 2021-11-12
<td> 1269.</td><td> OrthographicCamera cam = CheckRestrictions(vp);</td>
<td> 1270.</td><td> double scale = cam.Width / vp.Actualwidth;</td>
<td> 1271.</td><td> double x = scale * (pt.X - vp.Actualwidth /2) + cam.Position.X;</td>
<td> 1272. 1273.</td><td> double y = scale * (vp.ActualHeight / 2 - pt.Y) + cam.Position.Y;</td>
<td> 1274.</td><td> return new Point3D(x, y, 2);</td>
<td> 1275. 1276.</td><td> }</td>
<td> 1277.</td><td> 1 ! Converts a 3D point tc 2D in device-independent coordinates</td>
<td> 1278.</td><td> // relative to Viewport3D.</td>
<td> 1279.</td><td> private Point Simple3Dto2D(Viewport3D vp, Point3D point)</td>
<td> 1280.</td><td></td>
<td> 1281.</td><td> OrthographicCamera cam = CheckRestrictions(vp);</td>
<td> 1282.</td><td> double scale = vp.ActualWidth / cam.Width;</td>
<td> 1283.</td><td> double x = vp.ActualWidth / 2 + scale * (point.X cam.Position.X);</td>
<td> 1284.</td><td> double y = vp.ActualHeight / 2 - scale * (point.Y cam.Position.Y) ;</td>
<td> 1285.</td><td> return new Point(x, y) ;</td>
<td> 1286. 1287.</td><td> }</td>
<td> 1288.</td><td> private OrthographicCamera CheckRestrictions(Viewport3D vo)</td>
<td> 1289.</td><td> {</td>
<td> 1290. 1291.</td><td> OrthographicCamera cam = vp.Camera as OrthographicCamera;</td>
<td> 1292.</td><td> if (cam == null)</td>
<td> 1293. 1294.</td><td> throw new ArgumentException(Camera must be OrthographicCamera);</td>
<td> 1295.</td><td> if (cam.LookDirection ! = new Vector3D(0, 0, -1))</td>
<td> 1296. 1297.</td><td> throw new ArgumentException(Camera LookDirection must be (0, 0, -1));</td>
<td> 1298.</td><td> if (cam.UpDirection != new Vectcr3D(0, 1, 0))</td>
<td> 1299. 1300.</td><td> throw new ArgumentException(Camera UpDirection must be (0, 1, 0));</td>
<td> 1301.</td><td> return cam;</td>
<td> 1302. 1303.</td><td> )</td>
<td> 1304.</td><td> private RenderedWisp[] _renderedWisps;</td>
<td> 1305. 1306.</td><td> private RenderedDefaultPolygon[] _renderedDefaultPolygons;</td>
<td> 1307.</td><td> ΙΠ <summary></td>
<td> 1308.</td><td> III Indicates if user drags mouse</td>
<td> 1309.</td><td> III </summary></td>
<td> 1310. 1311.</td><td> private bool isDragging;</td>
<td> 1312. 1313.</td><td> private bool _isDraggingContent;</td>
104
Date Reçue/Date Received 2021-11-12
<td> 1314. 1315. 1316. 1317. 1318. 1319. 1320. 1321. 1322. 1323. 1324. 1325.</td><td> private RenderedWisp _draggingWisp = null; private RenderedPolygon _draggingPolygon = null; III <summary> III Indicates index of dragging vertex III </summary> private int _draggingVertexIndex; III <summary> III Start position for dragging mesh III </summary> private Point3D[] _startDraggingMeshPoints;</td>
<td> 1326. 1327. 1328. 1329. 1330. 1331. 1332. 1333. 1334. 1335.</td><td> III <summary> III Start position for mouse while dragging a mesh III </summary> private Point3D _startDraggingPoint; III <summary> III Start position of mouse while dragging III </summary> private Point _startDraggingMousePoint;</td>
<td> 1336. 1337. 1338.</td><td> III <summary> III Indicates that Control Points assigned from within control class</td>
<td> 1339. 1340. 1341. 1342. 1343. 1344. 1345. 1346. 1347. 1348. 1349. 1350. 1351. 1352. } 1353.</td><td> Ill </summary> private bool _internalChange = false; III <summary> III Indicates that control is loaded III </summary> private bool _loaded = false; III <summary> III Stores a list of all clicked click groups III </$ummary> private List<string> _clickedGroups = new List<string>(); J</td>
105
Contents6
28 sheets
Sheet 1 Sheet 2 Sheet 3 Sheet 4 Sheet 5 Sheet 6 Sheet 7 Sheet 8 Sheet 9 Sheet 10 Sheet 11 Sheet 12 Sheet 13 Sheet 14 Sheet 15 Sheet 16 Sheet 17 Sheet 18 Sheet 19 Sheet 20 Sheet 21 Sheet 22 Sheet 23 Sheet 24 Sheet 25 Sheet 26 Sheet 27 Sheet 28
53 members in 12 offices
Priority claims3
| Document | Office | Kind | Date |
|---|---|---|---|
| 62097769 | United States of America | – | |
| 201462097769 | United States of America | P | |
| 2971280 | Canada | A |
Members53
| Document | Office | Kind | |
|---|---|---|---|
| US2014333745A1 | United States of America | A1 | |
| US2015062089A1 | United States of America | A1 | |
| US9360888B2 | United States of America | B2 | |
| US2016191879A1 | United States of America | A1 | |
| CA2971280A1 | Canada | A1 | |
| CA3138907A1 | Canada | A1 | |
| WO2016109749A1 | World Intellectual Property Organization (WIPO) | A1 | |
| US9465488B2 | United States of America | B2 | |
| US2016378267A1 | United States of America | A1 | |
| US2017185228A1 | United States of America | A1 | |
| EP3241074A1 | European Patent Office (EPO) | A1 | |
| CN107430325A | China | A | |
| MX2017008609A | Mexico | A | |
| CA3072078A1 | Canada | A1 | |
| WO2019032616A1 | World Intellectual Property Organization (WIPO) | A1 | |
| EP3241074A4 | European Patent Office (EPO) | A4 | |
| CA3092636A1 | Canada | A1 | |
| WO2019169315A1 | World Intellectual Property Organization (WIPO) | A1 | |
| US2019315571A1 | United States of America | A1 | |
| AU2018316162A1 | Australia | A1 | |
| KR20200040800A | Republic of Korea | A | |
| CN111164531A | China | A | |
| WO2019032616A9 | World Intellectual Property Organization (WIPO) | A9 | |
| EP3665540A1 | European Patent Office (EPO) | A1 | |
| BR112020002530A2 | Brazil | A2 | |
| CA3132161A1 | Canada | A1 | |
| WO2020181149A1 | World Intellectual Property Organization (WIPO) | A1 | |
| AU2019227985A1 | Australia | A1 | |
| US2020312080A1 | United States of America | A1 | |
| JP2020530160A | Japan | A | |
| US2020371528A1 | United States of America | A1 | |
| MX2020001405A | Mexico | A | |
| CN107430325B | China | B | |
| EP3759420A1 | European Patent Office (EPO) | A1 | |
| US10891003B2 | United States of America | B2 | |
| CL2020000307A1 | Chile | A1 | |
| EP3665540A4 | European Patent Office (EPO) | A4 | |
| CN112631438A | China | A | |
| US2021117040A1 | United States of America | A1 | |
| EP3759420A4 | European Patent Office (EPO) | A4 | |
| CA2971280C | Canada | C | |
| US11233981B2 | United States of America | B2 | |
| US2022247984A1 | United States of America | A1 | |
| CA3138907CThis record | Canada | C | |
| CN112631438B | China | B | |
| EP3241074B1 | European Patent Office (EPO) | B1 | |
| JP7339238B2 | Japan | B2 | |
| AU2023274066A1 | Australia | A1 | |
| ZA202001211B | South Africa | B | |
| US12120471B2 | United States of America | B2 | |
| AU2024227562A1 | Australia | A1 | |
| MX389032B | Mexico | B | |
| US12429881B2 | United States of America | B2 |
14 legal events, as the office reported them to INPADOC
Over the term
Point at a mark for the eventEvents
| Event | Code | |
|---|---|---|
| Other event occurredST27 STATUS EVENT CODE: A-4-4-W10-W00-W100 (AS PROVIDED BY THE NATIONAL OFFICE); EVENT TEXT: LETTER SENTW00 | W00 | |
| Other event occurredST27 STATUS EVENT CODE: A-4-4-W10-W00-W100 (AS PROVIDED BY THE NATIONAL OFFICE); EVENT TEXT: LETTER SENTW00 | W00 | |
| Maintenance fee for patent paidMPN | MPN | |
| Fee paidST27 STATUS EVENT CODE: A-4-4-U10-U00-U101 (AS PROVIDED BY THE NATIONAL OFFICE); EVENT TEXT: MAINTENANCE REQUEST RECEIVEDU00 | U00 | |
| Full renewal or maintenance fee paidST27 STATUS EVENT CODE: A-4-4-U10-U11-U102 (AS PROVIDED BY THE NATIONAL OFFICE); EVENT TEXT: MAINTENANCE FEE PAYMENT DETERMINED COMPLIANTU11 | U11 | |
| Full renewal or maintenance fee paidST27 STATUS EVENT CODE: A-4-4-U10-U11-U102 (AS PROVIDED BY THE NATIONAL OFFICE); EVENT TEXT: MAINTENANCE FEE PAYMENT PAID IN FULLU11 | U11 | |
| Examination requestEEER | EEER | |
| Examination requestEEER | EEER | |
| Examination requestEEER | EEER | |
| Examination requestEEER | EEER | |
| Examination requestEEER | EEER | |
| Examination requestEEER | EEER | |
| Examination requestEEER | EEER | |
| Examination requestEEER | EEER |
Numbers
- Publication
- 3138907
- Application
- 3138907
Titles2
- English
- SYSTEM AND METHOD FOR INTERACTIVE PROJECTION
- French
- SYSTEME ET PROCEDE DE PROJECTION INTERACTIVE
Classification
- CPC, 10
- H04N9/3185
- G03B17/54
- G03B21/26
- G03B2206/00
- G06F3/0304
- G06F3/0425
- H04N9/3194
- H04N9/3147
- G06V20/52
- G06T3/08
- IPC, 2
- H04N5 74
- G06V40 16