Home

Resume

Blog

Teikitu


/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/*  »Project«   Teikitu Gaming System (TgS) (∂)
    »File«      TgS Collision - F - Linear-Linear.c_inc
    »Keywords«  Collision;Linear;Line;Ray;Segment;Point;Distance;Closest
    »Author«    Andrew Aye (EMail: mailto:andrew.aye@gmail.com, Web: http://www.andrewaye.com)
    »Version«   4.51 / »GUID« A9981407-3EC9-42AF-8B6F-8BE6DD919615                                                                                                        */
/*   -------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
/*  Copyright: © 2002-2017, Andrew Aye.  All Rights Reserved.
    This software is free for non-commercial use.  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
      following conditions are met:
        Redistribution of source code must retain this copyright notice, this list of conditions and the following disclaimers.
        Redistribution in binary form must reproduce this copyright notice, this list of conditions and the following disclaimers in the documentation and other materials
          provided with the distribution.
    The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
    The intellectual property rights of the algorithms used reside with Andrew Aye.
    You may not use this software, in whole or in part, in support of any commercial product without the express written consent of the author.
    There is no warranty or other guarantee of fitness of this software for any purpose. It is provided solely "as is".                                                   */
/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */

MSVC_WARN_DISABLE_PUSH( 6235 ) /* Analysis - (<non-zero constant> || <expression>) is always a non-zero constant. */
MSVC_WARN_DISABLE_PUSH( 6239 ) /* Analysis - (<non-zero constant> && <expression>) always evaluates to the result of <expression>. */
MSVC_WARN_DISABLE_PUSH( 6240 ) /* Analysis - (<expression> && <non-zero constant>) always evaluates to the result of <expression>. */


/*                                                                                                                                                                        */
/*  Segment Definition: G0(α) = P0 + α•D0 | α ε [ 0, 1]                                                                                                                   */
/*  Segment Definition: G1(β) = P1 + β•D1 | β ε [ 0, 1]                                                                                                                   */
/*                                                                                                                                                                        */
/* Derivation:                                                                                                                                                            */
/*  Let the points of closest contact be Q0 = P0+γ•D0 and Q1 = P1+Φ•D1, and v = Q1-Q0                                                                                     */
/*  Geometrically we know that the vector connecting the two closest points of contact ( or the minimal distance                                                          */
/*    vector ) must be perpendicular to both lines.  Thus, D0•v=0, D1•v=0, DS=P1-P0, v=(P1+Φ•D1)-(P0+γ•D0)                                                                */
/*                                                                                                                                                                        */
/*      v = (P1+Φ•D1) - (P0+γ•D0)                                                                                                                                         */
/*        = P1 + Φ•D1 - P0 - γ•D0                                                                                                                                         */
/*        = P1 - P0 + Φ•D1 - γ•D0                                                                                                                                         */
/*        = DS + Φ•D1 - γ•D0                                                                                                                                              */
/*                                                                                                                                                                        */
/*      0 = D0_(DS + Φ•D1 - γ•D0,DIM)               and     0 = D1_(DS + Φ•D1 - γ•D0,DIM)                                                                                 */
/*      0 = (DS•D0) + Φ_(D0•D1,DIM) - γ_(D0•D0,DIM)     and     0 = (DS•D1) + Φ_(D1•D1,DIM) - γ_(D0•D1,DIM)                                                               */
/*      γ = (DS•D0)/(D0•D0) + Φ_(D0•D1,DIM)/(D0•D0)     and     γ = (DS•D1)/(D0•D1) + Φ_(D1•D1,DIM)/(D0•D1)                                                               */
/*      Φ = γ_(D0•D0,DIM)/(D0•D1) - (DS•D0)/(D0•D1)     and     Φ = γ_(D0•D1,DIM)/(D1•D1) - (DS•D1)/(D1•D1)                                                               */
/*                                                                                                                                                                        */
/* Two equations, two unknowns - solving for the gamma and theta yields:                                                                                                  */
/*                                                                                                                                                                        */
/*      0 = γ_(D0•D0,DIM)T_(D1•D1,DIM) - (DS•D0)T_(D1•D1,DIM) - γ_(D0•D1,DIM)T_(D0•D1,DIM) + (DS•D1)T_(D0•D1,DIM)                                                         */
/*      0 = γ_((D0•D0,DIM)T_(D1•D1,DIM) - (D0•D1)T_(D0•D1,DIM)) + (DS•D1)T_(D0•D1,DIM) - (DS•D0)T_(D1•D1,DIM)                                                             */
/*      γ = ((DS•D0)T_(D1•D1,DIM) - (DS•D1)T_(D0•D1,DIM)) / ((D0•D0)T_(D1•D1,DIM) - (D0•D1)T_(D0•D1,DIM))                                                                 */
/*                                                                                                                                                                        */
/*      0 = Φ_(D1•D1,DIM)T_(D0•D0,DIM) + (DS•D1)T_(D0•D0,DIM) - Φ_(D0•D1,DIM)T_(D0•D1,DIM) - (DS•D0)T_(D0•D1,DIM)                                                         */
/*      0 = Φ_((D1•D1,DIM)T_(D0•D0,DIM) - (D0•D1)T_(D0•D1,DIM)) + (DS•D1)T_(D0•D0,DIM) - (DS•D0)T_(D0•D1,DIM)                                                             */
/*      Φ = ((DS•D0)T_(D0•D1,DIM) - (DS•D1)T_(D0•D0,DIM)) / ((D0•D0)T_(D1•D1,DIM) - (D0•D1)T_(D0•D1,DIM))                                                                 */
/*                                                                                                                                                                        */
/* If ((D0•D0)T_(D1•D1,DIM) - (D0•D1)T_(D0•D1,DIM)) < ε, the lines are parallel                                                                                           */
/*                                                                                                                                                                        */
/* However, we know that γ ε [ 0, 1], Φ ε [ 0, 1], generating nine cases:                                                                                                 */
/*                                                                                                                                                                        */
/* [1] γ ε (-∞, 0) | Φ ε (-∞, 0)                                                                                                                                          */
/*    [A] DS•D0 ε ( 0, D0•D0) || γ = DS•D0 / D0•D0 | Φ = 0                                                                                                                */
/*         = (P1 - P0 - γ•D0)T_(P1 - P0 - γ•D0,DIM)                                                                                                                       */
/*         = (DS - γ•D0)T_(DS - γ•D0,DIM)                                                                                                                                 */
/*         = (DS•DS) - 2•γ_(DS•D0,DIM) + γ•γ_(D0•D0,DIM)                                                                                                                  */
/*         = (DS•DS) + 2_(DS•D0 / D0•D0,DIM)T_(DS•D0,DIM) + (DS•D0 / D0•D0)T_(DS•D0 / D0•D0,DIM)T_(D0•D0,DIM)                                                             */
/*         = (DS•DS) - (DS•D0)T_(DS•D0,DIM) / (D0•D0)                                                                                                                     */
/*         = (DS•DS) - γ_(DS•D0,DIM)                                                                                                                                      */
/*    [B] DS•D0 ε ( D0•D0, ∞) || γ = 1 | Φ = 0                                                                                                                            */
/*         = (P1 - P0 - D0)T_(P1 - P0 - D0,DIM)                                                                                                                           */
/*         = (DS - D0)T_(DS - D0,DIM)                                                                                                                                     */
/*         = (DS•DS) - 2_(DS•D0,DIM) + (D0•D0)                                                                                                                            */
/*    [C] DS•D0 ε (-∞, 0), DS•D1 ε [ 0, ∞) || γ = 0 | Φ = 0                                                                                                               */
/*         = (P1 - P0)T_(P1 - P0,DIM)                                                                                                                                     */
/*         = (DS•DS)                                                                                                                                                      */
/*    [D] DS•D0 ε (-∞, 0), DS•D1 ε (-DS•D1, 0) || γ = 0 | Φ = -DS•D1 / D1•D1                                                                                              */
/*         = (P1 + Φ•D1 - P0)T_(P1 + Φ•D1 - P0,DIM)                                                                                                                       */
/*         = (DS + Φ•D1)T_(DS + Φ•D1,DIM)                                                                                                                                 */
/*         = (DS•DS) + 2•Φ_(DS•D1,DIM) + Φ•Φ_(D1•D1,DIM)                                                                                                                  */
/*         = (DS•DS) + 2•Φ_(DS•D1,DIM) + Φ_(-DS•D1 / D1•D1,DIM)T_(D1•D1,DIM)                                                                                              */
/*         = (DS•DS) + Φ_(DS•D1,DIM)                                                                                                                                      */
/*    [E] DS•D0 ε (-∞, 0), DS•D1 ε (-∞,-D1•D1] || γ = 0 | Φ = 1                                                                                                           */
/*         = (P1 + D1 - P0)T_(P1 + D1 - P0,DIM)                                                                                                                           */
/*         = (DS + D1)T_(DS + D1,DIM)                                                                                                                                     */
/*         = (DS•DS) + 2_(DS•D1,DIM) + (D1•D1)                                                                                                                            */
/*                                                                                                                                                                        */
/* [2] γ ε (-∞, 0) | Φ ε [ 0, 1]                                                                                                                                          */
/*    [A] DS•D1 ε [ 0, ∞) || γ = 0 | Φ = 0                                                                                                                                */
/*         Same as [1C]                                                                                                                                                   */
/*    [B] DS•D1 ε (-D1•D1, 0) || γ = 0 | Φ = -DS•D1 / D1•D1                                                                                                               */
/*         Same as [1D]                                                                                                                                                   */
/*    [C] DS•D1 ε (-∞,-D1•D1) || γ = 0 | Φ = 1                                                                                                                            */
/*         Same as [1E]                                                                                                                                                   */
/*                                                                                                                                                                        */
/* [3] γ ε (-∞, 0) | Φ ε ( 1, ∞)                                                                                                                                          */
/*    [A] DS•D0 ε [D0•D0 - D0•D1, ∞) || γ = 1 | Φ = 1                                                                                                                     */
/*         = (P1 + D1 - P0 - D0)T_(P1 + D1 - P0 - D0,DIM)                                                                                                                 */
/*         = (DS + D1 - D0)T_(DS + D1 - D0,DIM)                                                                                                                           */
/*         = (DS•DS) + (DS•D1) - (DS•D0) + (DS•D1) + (D1•D1) - (D0•D1) - (DS•D0) - (D0•D1) + (D0•D0)                                                                      */
/*         = (DS•DS) + 2_(DS•D1,DIM) - 2_(D0•D1,DIM) - 2_(DS•D0,DIM) + (D0•D0) + (D1•D1)                                                                                  */
/*    [B] DS•D0 ε (-D0•D1, D0•D0 - D0•D1) || γ = ((D0•D1) + (DS•D0)) / (D0•D0) | Φ = 1                                                                                    */
/*         = (P1 + D1 - P0 - γ•D0)T_(P1 + D1 - P0 - γ•D0,DIM)                                                                                                             */
/*         = (DS + D1 - γ•D0)T_(DS + D1 - γ•D0,DIM)                                                                                                                       */
/*         = (DS•DS) + 2_(DS•D1,DIM) + (D1•D1) - 2•γ_(D0•D1,DIM) - 2•γ_(DS•D0,DIM) + γ•γ_(D0•D0,DIM)                                                                      */
/*         = (DS•DS) + 2_(DS•D1,DIM) + (D1•D1) - γ_(2•(D0•D1,DIM) + 2_(DS•D0,DIM) - γ_(D0•D0,DIM))                                                                        */
/*         = (DS•DS) + 2_(DS•D1,DIM) + (D1•D1) - γ_(2•(D0•D1,DIM) + 2_(DS•D0,DIM) - (D0•D1) - (DS•D0))                                                                    */
/*         = (DS•DS) + 2_(DS•D1,DIM) + (D1•D1) - γ_((D0•D1,DIM) + (DS•D0))                                                                                                */
/*         = (DS•DS) + 2_(DS•D1,DIM) + (D1•D1) - γ•γ_(D0•D0,DIM)                                                                                                          */
/*    [C] DS•D0 ε (-∞,-D0•D1) | DS•D1 ε ( 0, ∞) || γ = 0 | Φ = 0                                                                                                          */
/*         Same as [1C]                                                                                                                                                   */
/*    [D] DS•D0 ε (-∞,-D0•D1) | DS•D1 ε (-D1•D1, 0) || γ = 0 | Φ = -DS•D1 / D1•D1                                                                                         */
/*         Same as [1D]                                                                                                                                                   */
/*    [E] DS•D0 ε (-∞,-D0•D1) | DS•D1 ε (-∞,-D1•D1) || γ = 0 | Φ = 1                                                                                                      */
/*         Same as [1E]                                                                                                                                                   */
/*                                                                                                                                                                        */
/* [4] γ ε [ 0, 1] | Φ ε (-∞, 0)                                                                                                                                          */
/*    [A] DS•D0 ε (-∞, 0) || γ = 0 | Φ = 0                                                                                                                                */
/*         Same as [1C]                                                                                                                                                   */
/*    [B] DS•D0 ε [ 0, D0•D0] || γ = DS•D0 / D0•D0 | Φ = 0                                                                                                                */
/*         Same as [1A]                                                                                                                                                   */
/*    [C] DS•D0 ε ( D0•D0, ∞) || γ = 1 | Φ = 0                                                                                                                            */
/*         Same as [1B]                                                                                                                                                   */
/*                                                                                                                                                                        */
/* [5] γ ε [ 0, 1] | Φ ε [ 0, 1]                                                                                                                                          */
/*     Distance: The distance value would be || v ||.                                                                                                                     */
/*       = || v || = v•v = (P1 + Φ•D1 - P0 - γ•D0)T_(P1 + Φ•D1 - P0 - γ•D0,DIM)                                                                                           */
/*       = (DS + Φ•D1 - γ•D0)T_(DS + Φ•D1 - γ•D0,DIM)                                                                                                                     */
/*       = (DS•DS) + 2•Φ_(DS•D1,DIM) - 2•γ_(DS•D0,DIM) + Φ•Φ_(D1•D1,DIM) - 2•γ•Φ_(D0•D1,DIM) + γ•γ_(D0•D0,DIM)                                                            */
/*       = (DS•DS) + Φ_(Φ•(D1•D1,DIM) + 2_(DS•D1,DIM)) + γ_(γ•(D0•D0,DIM) - 2_(DS•D0,DIM)) - 2•γ•Φ_(D0•D1,DIM)                                                            */
/*                                                                                                                                                                        */
/* [6] γ ε [ 0, 1] | Φ ε ( 1, ∞)                                                                                                                                          */
/*    [A] DS•D0 ε [D0•D0 - D0•D1, ∞) || γ = 1 | Φ = 1                                                                                                                     */
/*         Same as [3A]                                                                                                                                                   */
/*    [B] DS•D0 ε (-D0•D1, D0•D0 - D0•D1) || γ = ((D0•D1) + (DS•D0)) / (D0•D0) | Φ = 1                                                                                    */
/*         Same as [3B]                                                                                                                                                   */
/*    [C] DS•D0 ε (-∞,-D0•D1) || γ = 0 | Φ = 1                                                                                                                            */
/*         Same as [1E]                                                                                                                                                   */
/*                                                                                                                                                                        */
/* [7] γ ε ( 1, ∞) | Φ ε (-∞, 0)                                                                                                                                          */
/*    [A] DS•D0 ε (-∞, 0) || γ = 0 | Φ = 0                                                                                                                                */
/*         Same as [1C]                                                                                                                                                   */
/*    [B] DS•D0 ε [ 0, D0•D0) || γ = DS•D0 / D0•D0 | Φ = 0                                                                                                                */
/*         Same as [1A]                                                                                                                                                   */
/*    [C] DS•D0 ε ( D0•D0, ∞), DS•D1 ε ( D0•D1, ∞) || γ = 1 | Φ = 0                                                                                                       */
/*         Same as [1B]                                                                                                                                                   */
/*    [D] DS•D0 ε ( D0•D0, ∞), DS•D1 ε ( D0•D1 - D1•D1, D0•D1) || γ = 1 | Φ = ((D0•D1) - (DS•D1)) / (D1•D1)                                                               */
/*         = (P1 + Φ•D1 - P0 - D0)T_(P1 + Φ•D1 - P0 - D0,DIM)                                                                                                             */
/*         = (DS + Φ•D1 - D0)T_(DS + Φ•D1 - D0,DIM)                                                                                                                       */
/*         = (DS•DS) + 2•Φ_(DS•D1,DIM) + Φ•Φ_(D1•D1,DIM) - 2•Φ_(D0•D1,DIM) - 2_(DS•D0,DIM) + (D0•D0)                                                                      */
/*         = (DS•DS) + Φ_(2•(DS•D1,DIM) - 2_(D0•D1,DIM) + Φ_(D1•D1,DIM)) - 2_(DS•D0,DIM) + (D0•D0)                                                                        */
/*         = (DS•DS) + Φ_((DS•D1,DIM) - (D0•D1)) - 2_(DS•D0,DIM) + (D0•D0)                                                                                                */
/*         = (DS•DS) - Φ•Φ_(D1•D1,DIM) - 2_(DS•D0,DIM) + (D0•D0)                                                                                                          */
/*    [E] DS•D0 ε ( D0•D0, ∞), DS•D1 ε (-∞, D0•D1 - D1•D1) || γ = 1 | Φ = 1                                                                                               */
/*         Same as [3A]                                                                                                                                                   */
/*                                                                                                                                                                        */
/* [8] γ ε ( 1, ∞) | Φ ε [ 0, 1]                                                                                                                                          */
/*    [A] DS•D1 ε ( D0•D1, ∞) || γ = 1 | Φ = 0                                                                                                                            */
/*         Same as [1B]                                                                                                                                                   */
/*    [B] DS•D1 ε ( D0•D1 - D1•D1, D0•D1) || γ = 1 | Φ = ((D0•D1) - (DS•D1)) / (D1•D1)                                                                                    */
/*         Same as [7D]                                                                                                                                                   */
/*    [C] DS•D1 ε (-∞, D0•D1 - D1•D1) || γ = 1 | Φ = 1                                                                                                                    */
/*         Same as [3A]                                                                                                                                                   */
/*                                                                                                                                                                        */
/* [9] γ ε ( 1, ∞) | Φ ε ( 1, ∞)                                                                                                                                          */
/*    [A] DS•D0 ε [-D0•D1, D0•D0-D0•D1] || γ = ((D0•D1) + (DS•D0)) / (D0•D0) | Φ = 1                                                                                      */
/*         Same as [3B]                                                                                                                                                   */
/*    [B] DS•D0 ε (-∞,-D0•D1) || γ = 0 | Φ = 1                                                                                                                            */
/*         Same as [1E]                                                                                                                                                   */
/*    [C] DS•D0 ε ( D0•D0-D0•D1, ∞), DS•D1 ε ( D0•D1, ∞) || γ = 1 | Φ = 0                                                                                                 */
/*         Same as [1B]                                                                                                                                                   */
/*    [D] DS•D0 ε ( D0•D0-D0•D1, ∞), DS•D1 ε ( D0•D1 - D1•D1, D0•D1) || γ = 1 | Φ = ((D0•D1) - (DS•D1)) / (D1•D1)                                                         */
/*         Same as [7D]                                                                                                                                                   */
/*    [E] DS•D0 ε ( D0•D0-D0•D1, ∞), DS•D1 ε (-∞, D0•D1 - D1•D1) || γ = 1 | Φ = 1                                                                                         */
/*         Same as [3A]                                                                                                                                                   */
/*                                                                                                                                                                        */
/* -- Parallel Segments --                                                                                                                                                */
/*                                                                                                                                                                        */
/* [1] D0•D1 ε (-∞, 0)                                                                                                                                                    */
/*    [A] DS•D0 ε ( D0•D0-D0•D1, ∞) || γ = 1 | Φ = 1                                                                                                                      */
/*         Same as [3A]                                                                                                                                                   */
/*    [B] DS•D0 ε ( D0•D0, D0•D0-D0•D1] || γ = 1 | Φ = ((D0•D0) - (DS•D0)) / (D0•D1)                                                                                      */
/*         = (P1 + Φ•D1 - P0 - D0)T_(P1 + Φ•D1 - P0 - D0,DIM)                                                                                                             */
/*         = (DS + Φ•D1 - D0)T_(DS + Φ•D1 - D0,DIM)                                                                                                                       */
/*         = (DS•DS) + 2•Φ_(DS•D1,DIM) + Φ•Φ_(D1•D1,DIM) - 2•Φ_(D0•D1,DIM) - 2_(DS•D0,DIM) + (D0•D0)                                                                      */
/*         = (DS•DS) + 2•Φ_(DS•D1,DIM) + Φ•Φ_(D1•D1,DIM) - 2_((D0•D0,DIM) - (DS•D0)) - 2_(DS•D0,DIM) + (D0•D0)                                                            */
/*         = (DS•DS) + 2•Φ_(DS•D1,DIM) + Φ•Φ_(D1•D1,DIM) - 2_(D0•D0,DIM) + 2_(DS•D0,DIM) - 2_(DS•D0,DIM) + (D0•D0)                                                        */
/*         = (DS•DS) + 2•Φ_(DS•D1,DIM) + Φ•Φ_(D1•D1,DIM) - (D0•D0)                                                                                                        */
/*    [C] DS•D0 ε ( 0, D0•D0] || γ = DS•D0 / D0•D0 | Φ = 0                                                                                                                */
/*         Same as [1A]                                                                                                                                                   */
/*    [D] DS•D0 ε (-∞, 0) || γ = 0 | Φ = 0                                                                                                                                */
/*         Same as [1C]                                                                                                                                                   */
/*                                                                                                                                                                        */
/* [2] D0•D1 ε [ 0, ∞)                                                                                                                                                    */
/*    [A] DS•D0 ε [ D0•D0, ∞) || γ = 1 | Φ = 0                                                                                                                            */
/*         Same as [1B]                                                                                                                                                   */
/*    [C] DS•D0 ε (-D0•D1, D0•D0) || γ = 0 | Φ = -DS•D0 / D0•D1                                                                                                           */
/*         = (P1 + Φ•D1 - P0)T_(P1 + Φ•D1 - P0,DIM)                                                                                                                       */
/*         = (DS + Φ•D1)T_(DS + Φ•D1,DIM)                                                                                                                                 */
/*         = (DS•DS) + 2•Φ_(DS•D1,DIM) + Φ•Φ_(D1•D1,DIM)                                                                                                                  */
/*    [D] DS•D0 ε (-∞,-D0•D1] || γ = 0 | Φ = 1                                                                                                                            */
/*         Same as [1E]                                                                                                                                                   */


/* == Collision ========================================================================================================================================================= */

/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Public Functions                                                                                                                                                      */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

/* ---- VPM(tgCO_F,ParamSq) --------------------------------------------------------------------------------------------------------------------------------------------- */
/*  -- Internal Function -- bC0, bC1, bC2, bC3 : Indicate the termination condition of the linear {bc0,bC1}, {bC2,bC3}                                                    */
/*                                                                                                                                                                        */
/* Input:  vS0,vD0: Origin and Direction for Linear #1                                                                                                                    */
/* Input:  vS1,vD1: Origin and Direction for Linear #2                                                                                                                    */
/* Output:  _tyT0, _tyT1: Parametric parameter defining points of minimal distance on linear #1, and linear #2 respectively                                               */
/* Return: Minimal distance between the two linears or negative type max if they intersect.                                                                               */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */

TYPE VPM(tgCO_F,ParamSq)( TYPE *pfT0, TYPE *pfT1, V(CPC_TgVEC) pvS0, V(CPC_TgVEC) pvD0, V(CPC_TgVEC) pvS1, V(CPC_TgVEC) pvD1 )
{
    V(C_TgVEC)                          vDS = V(F_SUB)(pvS1, pvS0);

    const TYPE                          fD0_D0 = V(F_LSQ)(pvD0);
    const TYPE                          fD1_D1 = V(F_LSQ)(pvD1);
    const TYPE                          fD0_D1 = V(F_DOT)(pvD0, pvD1);

    const TYPE                          fDS_D0 = V(F_DOT)(&vDS, pvD0);
    const TYPE                          fDS_D1 = -V(F_DOT)(&vDS, pvD1);
    const TYPE                          fDS_DS = V(F_LSQ)(&vDS);

    const TYPE                          fDet = fD0_D0*fD1_D1 - fD0_D1*fD0_D1;
    TYPE                                fT0, fT1;

    TgPARAM_CHECK( pvS0 != pvS1 && pvD0 != pvD1 && pvS0 != pvD0 && pvS0 != pvD1 );
    TgPARAM_CHECK( V(F_Is_Point_Valid)(pvS0) && V(F_Is_Vector_Valid)(pvD0) );
    TgPARAM_CHECK( V(F_Is_Point_Valid)(pvS1) && V(F_Is_Vector_Valid)(pvD1) );

    if (fDet > F(KTgEPS)*fD0_D0*fD1_D1)
    {
        fT0 = fDS_D0*fD1_D1 + fDS_D1*fD0_D1;
        fT1 = fDS_D0*fD0_D1 + fDS_D1*fD0_D0;

        if (LN_CAP_0 && fT0 < MKL(0.0))
        {   /* == Negative region for Segment 0 == */
            if (LN_CAP_2 && fT1 < MKL(0.0))
            {   /* -- Negative region for Segment 1 -- */
                fT0 = F(tgCM_CLP)(fDS_D0 / fD0_D0, MKL(0.0), MKL(1.0));
                fT1 = fDS_D0 > MKL(0.0) ? MKL(0.0) : F(tgCM_CLP)(fDS_D1 / fD1_D1, MKL(0.0), MKL(1.0));
            }
            else if (!LN_CAP_3 || fT1 <= fDet)
            {   /* -- Interior region for Segment 1 -- */
                fT0 = MKL(0.0);
                fT1 = F(tgCM_CLP)(fDS_D1 / fD1_D1, MKL(0.0), MKL(1.0));
            }
            else
            {   /* -- Positive region for Segment 1 -- */
                V(C_TgVEC)                          vK0 = V(F_ADD)(&vDS, pvD1);
                const TYPE                          fDE_D0 = V(F_DOT)(pvD0, &vK0);

                fT0 = F(tgCM_CLP)(fDE_D0 / fD0_D0, MKL(0.0), MKL(1.0));
                fT1 = fDE_D0 > MKL(0.0) ? MKL(1.0) : F(tgCM_CLP)(fDS_D1 / fD1_D1, MKL(0.0), MKL(1.0));
            };
        }
        else if (!LN_CAP_1 || fT0 <= fDet)
        {   /* == Interior region for Segment 0 == */
            if (LN_CAP_2 && fT1 < MKL(0.0))
            {   /* -- Negative region for Segment 1 -- */
                fT0 = F(tgCM_CLP)(fDS_D0 / fD0_D0, MKL(0.0), MKL(1.0));
                fT1 = MKL(0.0);
            }
            else if (!LN_CAP_3 || fT1 <= fDet)
            {   /* -- Interior region for Segment 1 -- */
                fT0 = fT0 / fDet;
                fT1 = fT1 / fDet;
            }
            else
            {   /* -- Positive region for Segment 1 -- */
                V(C_TgVEC)                          vK0 = V(F_ADD)(&vDS, pvD1);
                const TYPE                          fDE_D0 = V(F_DOT)(pvD0, &vK0);

                fT0 = F(tgCM_CLP)(fDE_D0 / fD0_D0, MKL(0.0), MKL(1.0));
                fT1 = MKL(1.0);
            };
        }
        else
        {   /* == Positive region for Segment 0 == */
            V(C_TgVEC)                          vK0 = V(F_SUB)(&vDS, pvD0);
            const TYPE                          fDF_D1 = -V(F_DOT)(pvD1, &vK0);

            if (LN_CAP_2 && fT1 < MKL(0.0))
            {   /* -- Negative region for Segment 1 -- */
                fT0 = F(tgCM_CLP)(fDS_D0 / fD0_D0, MKL(0.0), MKL(1.0));
                fT1 = fDS_D0 > fD0_D0 ? MKL(0.0) : F(tgCM_CLP)(fDF_D1 / fD1_D1, MKL(0.0), MKL(1.0));
            }
            else if (!LN_CAP_3 || fT1 <= fDet)
            {   /* -- Interior region for Segment 1 -- */
                fT0 = MKL(1.0);
                fT1 = F(tgCM_CLP)(fDF_D1 / fD1_D1, MKL(0.0), MKL(1.0));
            }
            else
            {   /* -- Positive region for Segment 1 -- */
                V(C_TgVEC)                          vK1 = V(F_ADD)(&vDS, pvD1);
                const TYPE                          fDE_D0 = V(F_DOT)(pvD0, &vK1);

                fT0 = F(tgCM_CLP)(fDE_D0 / fD0_D0, MKL(0.0), MKL(1.0));
                fT1 = fDE_D0 <= fD0_D0 ? MKL(1.0) : F(tgCM_CLP)(fDF_D1 / fD1_D1, MKL(0.0), MKL(1.0));
            };
        };
    }
    else
    {
        /* Linears are parallel */

        const TYPE                          fDE_D0 = fDS_D0 + fD0_D1;
        const TYPE                          fDF_D1 = fD0_D1 - fDS_D1;

        TYPE                                fTest, fDSSQ = F(KTgMAX);

        fT0 = F(KTgMAX);
        fT1 = F(KTgMAX);

        if (fD0_D1 >= MKL(0.0))
        {
            /* Both segments have the same direction */

            if (LN_CAP_0 && LN_CAP_3 && ((fDS_D0 < MKL(0.0)) || (fDS_D1 > fD1_D1)))
            {
                /* First segment origin beyond second segment termination. */
                /* Second segment termination lies behind the first segment. */

                fTest = fDS_DS - MKL(2.0)*fDS_D1 + fD1_D1;
                if (fTest < fDSSQ)
                {
                    fDSSQ = fTest;
                    fT0 = MKL(0.0);
                    fT1 = MKL(1.0);
                };
            };

            if (LN_CAP_1 && LN_CAP_2 && ((fDS_D0 > fD0_D0) || ((-fDS_D1) > fD0_D1)))
            {
                /* First segment termination behind the second segment. */
                /* Second segment origin beyond the first segment. */

                fTest = fDS_DS - MKL(2.0)*fDS_D0 + fD0_D0;
                if (fTest < fDSSQ)
                {
                    fDSSQ = fTest;
                    fT0 = MKL(1.0);
                    fT1 = MKL(0.0);
                };
            };
        }
        else
        {
            /* The segments have opposing direction. */

            if (LN_CAP_1 && LN_CAP_3 && ((fDF_D1 > fD1_D1) || (fDE_D0 > fD0_D0)))
            {
                /*  First segment termination lies beyond the second segment termination. */
                V(C_TgVEC)                          vK0 = V(F_SUB)(&vDS, pvD0);
                V(C_TgVEC)                          vK1 = V(F_ADD)(&vK0, pvD1);

                fTest = V(F_LSQ)(&vK1);
                if (fTest < fDSSQ)
                {
                    fDSSQ = fTest;
                    fT0 = MKL(1.0);
                    fT1 = MKL(1.0);
                };
            };

            if (LN_CAP_0 && LN_CAP_2 && ((fDS_D0 < MKL(0.0)) || (fDS_D1 < MKL(0.0))))
            {
                /*  First segment origin lies behind the second segment origin. */

                if (fDS_DS < fDSSQ)
                {
                    fDSSQ = fDS_DS;
                    fT0 = MKL(0.0);
                    fT1 = MKL(0.0);
                };
            };
        };

        if ((!LN_CAP_2 || MKL(0.0) < fDS_D1) && (!LN_CAP_3 || fDS_D1 < fD1_D1))
        {
            /* First segment origin inside second segment. */

            const TYPE                          fK0 = fDS_D1 / fD1_D1;

            fTest = fDS_DS - fDS_D1*fK0;
            if (fTest < fDSSQ)
            {
                fDSSQ = fTest;
                fT0 = MKL(0.0);
                fT1 = fK0;
            };
        };

        if (LN_CAP_1 && (!LN_CAP_2 || MKL(0.0) < fDF_D1) && (!LN_CAP_3 || fDF_D1 < fD1_D1))
        {
            /* First segment termination inside second segment. */
            const TYPE                          fK0 = fDF_D1 / fD1_D1;
            V(C_TgVEC)                          vK0 = V(F_MUL_SV)(fK0, pvD1);
            V(C_TgVEC)                          vK1 = V(F_SUB)(pvD0, &vDS);
            V(C_TgVEC)                          vK2 = V(F_SUB)(&vK1, &vK0);

            fTest = V(F_LSQ)(&vK2);
            if (fTest < fDSSQ)
            {
                fDSSQ = fTest;
                fT0 = MKL(1.0);
                fT1 = fK0;
            };
        };


        if ((!LN_CAP_0 || MKL(0.0) <= fDS_D0) && (!LN_CAP_1 || fDS_D0 <= fD0_D0))
        {
            /* Second segment origin inside first segment. */

            const TYPE                          fK0 = fDS_D0 / fD0_D0;

            fTest = fDS_DS - fDS_D0*fK0;
            if (fTest < fDSSQ)
            {
                fDSSQ = fTest;
                fT0 = fK0;
                fT1 = MKL(0.0);
            };
        };

        if (LN_CAP_3 && (!LN_CAP_0 || MKL(0.0) < fDE_D0) && (!LN_CAP_1 || fDE_D0 <= fD0_D0))
        {
            /* Second segment termination inside first segment. */

            const TYPE                          fK0 = fDE_D0 / fD0_D0;
            V(C_TgVEC)                          vK0 = V(F_MUL_SV)(fK0, pvD0);
            V(C_TgVEC)                          vK1 = V(F_ADD)(&vDS, pvD1);
            V(C_TgVEC)                          vK2 = V(F_SUB)(&vK1, &vK0);

            fTest = V(F_LSQ)(&vK2);
            if (fTest < fDSSQ)
            {
                fDSSQ = fTest;
                fT0 = fK0;
                fT1 = MKL(1.0);
            };
        };

        TgERROR( fT0 < F(KTgMAX) && fT1 < F(KTgMAX) );
    };

    *pfT0 = fT0;
    *pfT1 = fT1;

    {
        V(C_TgVEC)                          vK0 = V(F_MUL_SV)(fT0, pvD0);
        V(C_TgVEC)                          vK1 = V(F_MUL_SV)(fT1, pvD1);
        V(C_TgVEC)                          vK3 = V(F_SUB)(&vDS, &vK0);
        V(C_TgVEC)                          vK4 = V(F_ADD)(&vK3, &vK1);

        return (V(F_LSQ)(&vK4));
    }
}


MSVC_WARN_DISABLE_POP( 6235 )
MSVC_WARN_DISABLE_POP( 6239 )
MSVC_WARN_DISABLE_POP( 6240 )