精华内容
下载资源
问答
  • 变分法证明两点之间线段最短

    万次阅读 2019-01-08 16:27:33
    在Part 2., 我们会以用这次介绍的内容和上述方程解决两点之间直线最短的问题为开头,继续介绍变分法。 ----------------------------------------------------------------------------------------------------...

    传送门https://zhuanlan.zhihu.com/yueaptx

    变分法简介Part 1.(Calculus of Variations)

    Dr.Stein

    Dr.Stein

    计算力学

    ​关注他

    283 人赞了该文章

    1. 泛函数 (Functionals)

     

    简而言之,泛函数是函数的函数,即它的输入是函数,输出是实数。而这个输出值取决于一个或多个函数(输入)在一整个路径上的积分而非像一般函数一样取决于离散的变量。这样说可能还是比较抽象,不过坚持看到下文的Example 1就可以更好理解了。

    通常在变分法中,泛函数是一个积分,记做I

    I(y)=\int_{x1}^{x2}Fdx

    其中我们想要通过选择被积函数F来最大化或最小化泛函数I的值。同时我们称F为拉格朗日函数(Lagrange function)。F可以是函数y(x)y(x)各阶导数的函数(以下y(x)均简写成y)。为了说明方便,我们先姑且设Fyy'的函数,所以我们可以进一步将泛函数I写成:

    I(y)=\int_{x1}^{x2}F(y,y';x)dx

    积分里面我用分号;将x和前面的y隔开代表yy'x的函数。一般Fy的函数关系是已知的,所以想要最大或最小化泛函数,实际上是通过选择适当的函数y(x)

    为了透彻理解这个概念,我们可以来看一个简单的例子。

    Example 1.

    一个最简单直观的例子是求两个固定点之间的最短路径。当然大家都知道两点之间直线最短,这里可以用变分法做出解释。

    如上图所示路径是一任意路径,我们取区中一小段微元ds,可以容易计算微元断的长度为:

    ds^2=dx^2+dy^2=[1+(y')^2]dx^2,即:

    ds=\sqrt{1+(y')^2}dx

    积分得到总的路径长度为:

    L=\int_{x1}^{x2}ds=\int_{x1}^{x2}\sqrt{1+(y')^2}dx

    这个例子中,L是泛函数,\sqrt{1+(y')^2}是拉格朗日函数F,我们想要找一个函数y(x)使得泛函数L的值最小。这次Part 1.的任务就是为解决这个问题做准备。Part 2.中我们会用变分法证明这个y(x)确实是直线的方程。

    2. 泛函数的极值

     

    这里重申下,泛函数I在区间[x_1,x_2]上的值取决于积分路径的选择,即取决于函数y(x)的选择。我们有理由假设存在一个这样的y(x),可以使得泛函数I取到极值。而在这个y(x)附近的任意路径我们记做\tilde{y}(x)。另外,我们假设y(x)两阶可微。通过引入一个微小量\epsilon\ll 1和一个任意可微函数\eta(x),我们可以用y(x)表示\tilde{y}(x):

    \tilde{y}(x)=y(x)+\epsilon\eta(x)

    这样做的好处是对于一个给定的\eta(x),我们可以通过改变\epsilon的值来得到无穷多的路径,同时对于任何\eta(x),当\epsilon=0的时候,\tilde{y}(x)y(x)重合。

    图像直观表示如下图:

    由于在边界条件的限制,\eta(x_1)=\eta(x_2)=0。这样就能保证\tilde{y}(x)可以通过两个固定端点。

    这时我们可以说,y(x)所对应的泛函数I的值是泛函数\tilde{I}=\int_{x_1}^{x_2}F(\tilde{y},\tilde{y}';x)dx的极值。我们可以进一步用\epsilon表示\tilde{I}

    \tilde{I}=\int_{x_1}^{x_2}F(\tilde{y},\tilde{y}';x)dx=\int_{x1}^{x_2}F(y+\epsilon\eta,y'+\epsilon\eta';x)dx

    虽然y(x)未知,但是根据之前的合理假设,y(x)是一个存在的确定函数。所以根据上式,如果给定一个特定的\eta(x)\tilde{I}的变化只取决于\epsilon的变化。所以我们现在可以把\tilde{I}看做是\epsilon的函数。用泰勒展开公式将\tilde{I}\epsilon=0处展开得到:

    \tilde{I}(\epsilon)=\tilde{I}|_{\epsilon=0}+(\frac{d\tilde{I}}{d\epsilon})\Big|_{\epsilon=0}\cdot\epsilon+ (\frac{d^2\tilde{I}}{d\epsilon^2})\Big|_{\epsilon=0}\cdot\frac{\epsilon^2}{2!} +\cdot \cdot \cdot =\tilde{I}_0+\tilde{I}_1\epsilon+\tilde{I}_2\epsilon^2+\cdot \cdot \cdot

    很明显,当\epsilon=0时,\tilde{I}|_{\epsilon=0}=I,带入上式可得到:

    \tilde{I}-I=\tilde{I}_1\epsilon+\tilde{I}_2\epsilon^2+\cdot \cdot \cdot

    这里我们记\delta I=\tilde{I}_1\epsilon=\frac{d\tilde{I}}{d\epsilon}\Big|_{\epsilon=0}\cdot\epsilon,并称之为一阶变分。同理二阶变分为\delta I^2=\tilde{I}_2\epsilon^2

    (这里插一句变分和微分的区别。变分在上图的直观解释是\tilde{y}y在竖直方向上的距离,称之为\delta y,所以这个差是在同一个x上计算的。而微分则是由于x的微小变动引起的y的变动。)

    然后我们可以类比求函数极值时的做法。求函数极值时,我们会令函数的一阶导数为零。这里同样,为了求泛函数\tilde{I}的极值,我们令一阶变分\delta I=0。现在我们计算化简\delta I:

    \delta I=(\int_{x_1}^{x_2}\frac{d\tilde{F}}{d\epsilon}\Big|_{\epsilon=0} dx)\cdot\epsilon
    \frac{d\tilde{F}}{d\epsilon}\Big|_{\epsilon=0} \cdot\epsilon=(\frac{\partial\tilde{F}}{\partial\tilde{y}}\cdot\frac{d\tilde{y}}{d\epsilon}+  \frac{\partial\tilde{F}}{\partial\tilde{y'}}\cdot\frac{d\tilde{y'}}{d\epsilon})\Big|_{\epsilon=0}\cdot\epsilon

    因为 \tilde{y}(x)=y(x)+\epsilon\eta(x), 不难得到:\frac{d\tilde{y}}{d\epsilon}=\eta,\frac{d\tilde{y'}}{d\epsilon}=\eta',另外我们有\delta y=\epsilon \eta,\delta y'=\epsilon\eta'

    又因为当\epsilon\rightarrow 0时,\tilde{F}\rightarrow 0, \tilde{y}\rightarrow y,\tilde{y}'\rightarrow y',将这些式子带入原式可以得到:

    \delta I=\int_{x_1}^{x_2}(\frac{\partial F}{\partial y}\delta y+\frac{\partial F}{\partial y'}\delta y')dx

    终于到最后一步啦,分部积分一下得到:

    \delta I=\int_{x_1}^{x_2}(\frac{\partial F}{\partial y}-\frac{d}{dx}(\frac{\partial F}{\partial y'} ))\delta ydx+\frac{\partial F}{\partial y'}\delta y\Big|_{x_1}^{x_2}

    \delta I=0就可以解得最小化泛函数的y啦。我们注意到\delta I有两个部分。对于第一个积分部分,由于\delta y是任意的,所以要想使这个部分等于零,需要保证^{[1]}

    \frac{\partial F}{\partial y}-\frac{d}{dx}(\frac{\partial F}{\partial y'} )=0 (x_1\leq x\leq x_2)

    这就是传说中的欧拉-拉格朗日方程(E-L equation)。

    而第二部分等于零则是边界条件。

    在Part 2., 我们会以用这次介绍的内容和上述方程解决两点之间直线最短的问题为开头,继续介绍变分法。

    ---------------------------------------------------------------------------------------------------------------------------

    注[1]:

    假设x_1x_2是给定的常数,\phi(x)是一个特定的在x_1\leq x\leq x_2上连续的函数,那么如果对于任意连续可微的函数\eta(x)都成立\int_{x_1}^{x_2}\phi(x)\eta(x)dx=0,则\phi(x)=0 (x_1\leq x\leq x_2)。

    (任意函数和一个非零的特定函数的乘积仍是任意函数,由于无法保证任意函数的积分是零,所以这个特定函数必须在这个区间上恒等于零使得乘积为零,这样可以保证积分为零。)

    展开全文
  • 计算两点间距离,点与线段距离,三个点的夹角
  • 线段交点个数的公式Download project - 72.6 KB 下载项目-72.6 KB Download source files - 40 KB 下载源文件40 KB 介绍 (Introduction) The people working around with some graphics code, very often ...

    求点到线段交点个数的公式

    Image 1

    介绍 (Introduction)

    The people working around with some graphics code, very often run into the problem of clipping line segments. It is a well-known problem and there have been a lot of algorithms provided. However, it is still a boring procedure and I've searched around for some feasible algorithms and finally, I found out the compact ant simply vector formula. In this article, the sample of the completed codes of anyhow segments clipping in MFC have been provided.

    人们在处理一些图形代码时,经常会遇到裁剪线段的问题。 这是一个众所周知的问题,并且提供了很多算法。 但是,这仍然是一个无聊的过程,我一直在寻找一些可行的算法,最后,我找到了简单的紧凑型蚁向量公式。 本文中提供了MFC中片段剪辑的完整代码示例。

    背景 (Background)

    The calculation of the intersection point of two line segments is based on the so-called wedge product of the two vectors; there are three performances of the wedge product of the two vectors completely interchanging:

    两个线段的交点的计算是基于两个向量的所谓楔积。 完全互换的两个向量的楔积的三个性能:

    Image 2

    The vector formula for the calculation of the intersection point of the two lines defined by the line segments:

    用于计算由线段定义的两条线的交点的向量公式:

    Image 3

    The formula (1) is valid just in condition r1^r0≠0. Also, it is clear that in computer calculations, no “pure zero” maybe not obtained while working with the float and double values. Therefore, for programming codes, this condition should be performed as:

    公式(1)仅在条件r1 ^ r0 ≠0时有效。 同样,很明显,在计算机计算中,使用floatdouble float值可能不会获得“纯零”。 因此,对于编程代码,此条件应按以下方式执行:

    Image 4

    If the condition (2) is valid, the coordinates of the intersection point R of the two lines is defined by the line segments to be obtained by the formula (1). It is not clear yet if the segments intersected themselves. The intersection of the segments to be established with the scalar product of the vectors. Intersection condition of the segments has been demonstrated in figure 2:

    如果条件(2)成立,则两条线的交点R的坐标由要通过公式(1)获得的线段定义。 目前尚不清楚这些片段是否相交。 要建立的线段与向量的标量积的交集。 段的相交条件已在图2中进行了演示:

    Image 5

    If the condition (3) is not valid, the segments are not intersected. Nevertheless, the scalar product of the vectors may provide valuable information on the relative positions of the segments concerned:

    如果条件(3)无效,则不相交。 然而,向量的标量积可能会提供有关段的相对位置的有价值的信息:

    Image 6

    The same for another segment:

    对于其他细分市场也是如此:

    Image 7

    And the condition when the lines defined by the segments do not intersect the segments themselves:

    线段定义的线不与线段本身相交的情况:

    Image 8

    If condition (2) is not valid, the segments and the lines defined by them are collinear and there is nothing of the point of intersection if the segments lay not in one line. The condition of the collinear vectors not to be in one line is defined by wedge product in the formula (7) and represented in figure 6:

    如果条件(2)无效,则线段和由它们定义的线是共线的,如果线段不在一条线上,则没有任何交点。 共线矢量不在一条直线上的条件由公式(7)中的楔乘积定义,如图6所示:

    Image 9

    If conditions (2) and (7) are not valid, the segments are placed in one line and maybe overlapped in some areas. The conditions of overlapping may also be established by means of the scalar product and it is worth distinguishing different cases as the segments are collinear in the same direction(r1∙r0>0), or the contrary one(r1∙r0<0), figure 7 and figure 8:

    如果条件(2)和(7)无效,则将这些段放在一行中,并且在某些区域可能重叠。 重叠的条件也可以通过标量积来确定,因此值得区分不同的情况,因为线段在同一方向( r1∙r0 > 0)或相反( r1∙r0 <0)是共线的,图7和图8:

    Image 10

    图片10

    Conditions of the collinear segments not overlapping have been provided in figure 9:

    共线段不重叠的条件已在图9中提供:

    Image 12

    The above is a complete set to provide valuable information about the relative positions of the segments. Needless to say, this technology may be applied to any programming language. The main advantage of the formula (1) provided is that it can be used in the graphics programming almost in the same form as performed in this article. In order to check all the technology above, the author developed a computer program in Visual C++ MFC (Microsoft Foundation Classes) with anyhow segments randomly created, randomly rotating and randomly moving and clipping at arbitrary point of time, just press “Enter” button. The vectors' behavior has to be defined regarding edge product, scalar product, and some other special routine mathematical properties.

    上面是一个完整的集合,可提供有关段的相对位置的有价值的信息。 不用说,该技术可以应用于任何编程语言。 所提供的公式(1)的主要优点是,它几乎可以以与本文所用的相同形式用于图形编程。 为了检查上述所有技术,作者在Visual C ++ MFC(Microsoft基础类)中开发了一个计算机程序,该程序具有任意创建的段,在任意时间点随机旋转,随机移动和剪切,只需按“ Enter ”按钮。 必须针对边积,标量积和一些其他特殊的常规数学属性定义矢量的行为。

    The demo project Segment2D has been created with the standard MFC App wizard. Vector performance is the same as class Polygon_2D and class Vector_2D in my former CodeProject article "Weiler-Atherton algorithm in MFC". The segments are randomly created and randomly moving and randomly rotating.

    演示项目Segment2D已使用标准MFC App向导创建 矢量性能与我以前的CodeProject文章“ MFC中的Weiler-Atherton算法 ”中的class Vector_2D class Polygon_2Dclass Vector_2D class Polygon_2D相同。 这些段是随机创建的,随机移动和随机旋转的。

    Before you start building the project provided, it is highly recommended to have a look at the demo presentation enclosed to get an idea of the output expected.

    在开始构建提供的项目之前,强烈建议您看一下随附的演示演示,以了解预期的输出。

    演示说明 (Demo Explanations)

    The executable Segment2D.exe has been built with MSVS-2015 pro using the instruments of MSVS-2010. Therefore the Segment2D.exe is valid even for Windows-XP (as opposed to my former CodeProject articles, no special *.dll files are required because of the RAM used only).

    可执行文件Segment2D.exe已使用MSVS-2010的工具与MSVS-2015 pro一起构建。 因此, Segment2D.exe甚至对于Windows-XP也有效(与我以前的CodeProject文章相反,由于仅使用了RAM,因此不需要特殊的* .dll文件)。

    Some menu and some special Accelerator keys have been arranged in order to demonstrate the Segment2D project implementation:

    为了演示Segment2D项目的实现,已经安排了一些菜单和一些特殊的Accelerator键:

    Image 13
    • Menu File->Play - play/stop object rotation (also Ctrl+P click)

      菜单文件 -> 播放 -播放/停止对象旋转(也按Ctrl + P 点击)

    • Menu Edit->Reset Scene->Random - two somehow segments with the random rotation and moving rates created (also Space Bar click)

      菜单编辑 -> 重置场景 -> 随机 -创建了两个具有随机旋转和移动速率的段(也可以单击空格键)

    • Menu Edit->Reset Scene->Collinear - two somehow collinear segments with the random moving rates created (also Ctrl+Space Bar click)

      菜单编辑 -> 重置场景 -> 共线 -创建具有随机移动速率的两个共线段(也按Ctrl +空格键单击)

    • Menu Edit->Reset Scene->Overlapping - two somehow segments in line with the random moving rates created (also Alt+Space Bar click)

      菜单编辑 -> 重置场景 -> 重叠 -与创建的随机移动速度一致的两个分段(也可以单击Alt +空格键)

    • Menu Edit->Start Clipping - stop segments rotation and moving and start clipping (also Enter click)

      菜单编辑 -> 开始剪切 -停止线段的旋转和移动,并开始剪切(也请输入 click)

    • Menu Edit->Next Scene - next scene of performance (if play stopped; also Right Arrow click)

      菜单编辑 -> 下一个场景 -表演的下一个场景(如果播放停止;也请单击向右箭头 )

    • Menu Help->Help - show Help Dialog (also F1 click)

      菜单帮助 -> 帮助 -显示帮助对话框 (也可以按F1键)

    The Help Dialog is non-modal therefore you can use as menu and accelerator commands directly or press an OK button in the Help Dialog (or double click the item correspondence):

    帮助”对话框是非模式的,因此您可以直接用作菜单和加速器命令,也可以在“ 帮助”对话框中按“ 确定”按钮(或双击项目对应项):

    Image 14

    建筑笔记 (Building Notes)

    Solution configuration must be installed as Release and the platform to be x86.

    解决方案配置必须安装为Release ,平台必须安装为x86

    The project provided has been developed with MSVS-2015 pro using the instruments of MSVS-2010. Therefore the EXE files are valid even for Windows-XP. If you do not need to run the application in Windows-XP, just change the instruments to MSVS-2015.

    提供的项目已使用MSVS-2010的工具与MSVS-2015 pro一起开发。 因此, EXE文件即使对于Windows-XP也是有效的。 如果不需要在Windows-XP中运行该应用程序,只需将仪器更改为MSVS-2015即可

    The default coding property is UNICODE; nevertheless MBCS coding is also available, just change the property.

    默认的编码属性是UNICODE ; 但是,也可以使用MBCS编码,只需更改属性即可。

    Even if you are working for the first time with MSVS, just select menu Debug->Start without debugging and the program Segment2D.exe should start building and working.

    即使你正在为第一次与MSVS,只要选择菜单调试 - > 启动 而不调试和程序Segment2D.exe应当建立和工作。

    项目源和数据存储 (Project Source and Data Storage)

    Standard source codes in Segment2Dproj path have been created with the standard MFC Application Wizard:

    Segment2Dproj路径中的标准源代码已使用标准MFC应用程序向导创建:

    • Segment2D.cpp - defines the standard class behaviors for the application

      Segment2D.cpp-定义应用程序的标准类行为

    • MainFrm.cpp - implementation of the standard CMainFrame class

      MainFrm.cpp-标准CMainFrame class

    • CChildView.cpp - implementation of the standard CWnd class; messages handling procedures created by the author using standard MFC Application Wizard procedures

      CChildView.cpp-标准CWnd class ; 作者使用标准MFC应用程序向导过程创建的消息处理过程

    • DlgHelp.cpp - non-modal implementation of the standard CDialogEx class; messages handling procedures created by the author using standard MFC Application Wizard procedures

      DlgHelp.cpp-标准CDialogEx class非模式实现; 作者使用标准MFC应用程序向导过程创建的消息处理过程

    • Segment2D.rc and resource.h - menu, dialog, accelerator resources created by the author using the standard Resource Wizard procedures

      Segment2D.rcresource.h-作者使用标准资源向导过程创建的菜单,对话框,加速器资源

    Special source codes in Segment2DProj\GlobUse path have been developed by the author based on the standard graphics and geometry routine procedures:

    作者根据标准的图形和几何例程程序开发了Segment2DProj \ GlobUse路径中的特殊源代码:

    • Vector_2D.cpp, Poligon_2D.cpp - 2D object handling

      Vector_2D.cppPoligon_2D.cpp -2D对象处理

    代码说明 (Code Explanation)

    All the Menu and Accelerator Commands have been done with standard MFC AppWizard technologies. And this article has no purpose to explain Segment2D demo project. If required, you may refer to my former article "Weiler-Atherton algorithm in MFC" where the InitApplication and DrawScene Procedure has been described. The main idea of this article is to explain the use of the Magic Formula of the intersection point of two line segments.

    所有菜单加速器命令均已使用标准MFC AppWizard技术完成。 并且本文无意解释Segment2D演示项目。 如果需要,可以参考我以前的文章“ MFC中的Weiler-Atherton算法 ”,其中描述了InitApplicationDrawScene Procedure 。 本文的主要思想是解释两个线段交点的魔术公式的用法。

    While declaring class Vector_2D, the main operations with the vectors are to be predetermined:

    在声明class Vector_2D ,要预先确定向量的主要操作:

    class Vector_2D : public CObject
    { 
    public:
    double x,y;
    Vector_2D ( const Vector_2D& v ){ x = v.x; y = v.y;};
    Vector_2D(double vx, double vy) { x = vx; y = vy; };
    friend Vector_2D operator + ( const Vector_2D&,  const Vector_2D& ); 
    friend Vector_2D operator - ( const Vector_2D&,  const Vector_2D& ); 
    friend double operator * ( const Vector_2D&,  const Vector_2D& ); 
    friend Vector_2D operator * ( double,  const Vector_2D& ); 
    friend Vector_2D operator * ( const Vector_2D&, double  ); 
    friend Vector_2D operator / ( const Vector_2D&, double  ); 
    friend Vector_2D operator / ( const Vector_2D&, const Vector_2D&  );
    friend Vector_2D operator & ( const Vector_2D& u, const Vector_2D& v  )
                                { return (u.x + v.x, u.y + v.y);};
    friend double operator ^ ( const Vector_2D& u, const Vector_2D& v  )
                             {return (u.x*v.y - u.y*v.x);}; 
    friend double operator | ( const Vector_2D &u, const Vector_2D &v  )
                             { return (u.x * v.x + u.y * v.y );};
    };
    inline Vector_2D Normalize ( Vector_2D& v ) 
         { double vv = !v;  return vv > GeomTreshold ? v /vv : Vector_2D(0); };     
    inline Vector_2D  operator + ( const Vector_2D& u,  const Vector_2D& v )
         { return Vector_2D( u.x + v.x, u.y + v.y );}
    inline Vector_2D  operator - ( const Vector_2D& u,  const Vector_2D& v )
         { return Vector_2D( u.x - v.x, u.y - v.y );}
    inline double  operator *  ( const Vector_2D& u,  const Vector_2D& v )
         {  return  u.x * v.x + u.y * v.y;}
    inline Vector_2D  operator *  ( const Vector_2D& u,  double f )
         {  return Vector_2D( u.x * f, u.y * f);}
    inline Vector_2D  operator *  ( double f, const Vector_2D& u )
         {return Vector_2D( f * u.x , f * u.y  );}
    inline Vector_2D  operator /  ( const Vector_2D& u,  double f )
         {  return Vector_2D( u.x / f, u.y / f );}
    inline Vector_2D&    Vector_2D::operator += ( const Vector_2D& v )
         {  x += v.x;  y += v.y;   return * this;}
    inline Vector_2D&    Vector_2D::operator -= ( const Vector_2D& v )
         {  x -= v.x;  y -= v.y;  return * this;}
    inline Vector_2D&    Vector_2D::operator *= ( double  v ){  x *= v;  y *= v;  return * this;}
    inline Vector_2D&    Vector_2D::operator *= ( const Vector_2D& v )
         {  x *= v.x;  y *= v.y;  return * this;}
    inline Vector_2D&    Vector_2D::operator /= ( double  v ){  x /= v;  y /= v;  return * this;}
    
    

    The intersection point of two lines is determined by segments to be calculated in one line:

    两条线的交点由要在一条线中计算的线段确定:

    Vector_2D R = (r0 * (R11^R10) - r1 *(R01^R00)) / (r1^r0);
    
    
    

    And once the intersection point of two lines has been determined by the segments received, it is easy to estimate if the point belongs to the segments with the scalar product calculation as in the Background part of this article prescribed.

    而且,一旦根据接收到的线段确定了两条线的交点,就可以通过标量乘积计算轻松估算出该点是否属于线段,如本文背景部分所述。

    The overlapping conditions of the collinear segments in line calculated by the function followed:

    该函数计算的直线上的共线段的重叠条件如下:

    BOOL isOverlapping(Vector_2D R00, Vector_2D R01, Vector_2D R10, 
          Vector_2D R11, Vector_2D * Q0, Vector_2D * Q1)
    {
    	Vector_2D r0 = R01 - R00;
    	Vector_2D r1 = R11 - R10;
    	if (fabs(r1^r0 / (!r1 * !r0)) > GeomTreshold)
    		return FALSE;
    	if (fabs((R10 - R00) ^ r0 / (!(R10 - R00) * !r0)) > GeomTreshold)
    		return FALSE;
    	if(r0*r1 >0)                            //if segments in same direction
    	if ((R00 - R10)* (R00 - R11) <= 0)      //if R00 is inside the segment(R10, R11)
    	{
    		*Q0 = R00;
    		if ((R01 - R10)* (R01 - R11) <= 0)  //if R01 is inside the segment(R10, R11)
    			*Q1 = R01;
    		else
    	      *Q1 = R11;
    	}
    	else
    		if ((R10 - R00)* (R10 - R01) < 0)   //if R10 is inside the segment(R00, R01)
    		{
    			*Q0 = R10;
    			if ((R01 - R10)* (R01 - R11) <= 0) //if R01 is inside the segment(R10, R11)
    				*Q1 = R01;
    			else
    				*Q1 = R11;
    		}
    		else;
    	else                      //if segments in contrary direction
    		if ((R00 - R10)* (R00 - R11) <= 0)  //if R00 is inside the segment(R10, R11)
    		{
    			*Q0 = R00;
    			if ((R01 - R10)* (R01 - R11) <= 0) //if R01 is inside the segment(R10, R11)
    				*Q1 = R01;
    			else
    				*Q1 = R10;
    		}
    		else
    			if ((R11 - R00)* (R11 - R01) < 0)  //if R11 is inside the segment(R00, R01)
    			{
    				*Q0 = R11;
    				if ((R01 - R10)* (R01 - R11) <= 0) //if R01 is inside the segment(R10, R11)
    					*Q1 = R01;
    				else
    					*Q1 = R10;
    			}
    			else
    				return FALSE;
    	return TRUE;
    }
    }
    
    

    使用提供的项目进行自己的应用程序开发 (Your Own Application Development Using the Project Provided)

    I hope that my explanations in the Background part of this article are quite clear so everybody can use this technology in any programming language.

    我希望我在本文的背景技术部分的解释很清楚,以便每个人都可以在任何编程语言中使用该技术。

    You may pick up this entire project, rename it with the project of my former CodeProject article "MFC Project from Existing Code in One Click" and combine and improve the code as you like.

    您可以选择整个项目,并用我以前的CodeProject文章“ 一键来自现有代码的MFC项目 ”中的项目将其重命名,然后根据需要组合和改进代码。

    Or you may pick up the GlobUse directory from this project and include the special procedures contained in any of your own graphics projects with menu Project->Existing Item.

    否则您可能会拿起GlobUse 该项目的目录,并通过菜单Project-> Existing Item包含任何您自己的图形项目中包含的特殊过程

    Your references to my code if any, should be highly appreciated.

    您对我的代码的引用(如果有的话)应受到高度赞赏。

    兴趣点 (Points of Interest)

    The main interest point is why I've not found this magic formula in any authoritative sources. It is easy to use even in the school level of geometry. Sure if we unpack this formula using the standard coordinate performance finally should be obtained as an enormous algorithm as provided a lot of on the internet. But I'm sure a few people should come back to the boring procedures after they use this formula.

    主要的兴趣点是为什么我在任何权威资料中都没有找到这个神奇的公式。 即使在学校的几何学水平上也很容易使用。 可以肯定的是,如果我们使用标准坐标性能来解开该公式,最终应该作为互联网上大量提供的巨大算法来获得。 但是我敢肯定,使用此公式后,有些人应该回到无聊的过程中。

    I believe that this demo and code should be helpful for software people for segments clipping.

    我认为,此演示和代码对于软件人进行片段裁剪应该会有所帮助。

    The project has been developed in the MFC platform. Nevertheless, everything developed in MFC may be converted to Win32 and vice versa.

    该项目已在MFC平台中开发。 但是,用MFC开发的所有内容都可以转换为Win32 ,反之亦然。

    The gif in the title of this article has been created with the program of my former CodeProject article "Your Own Avishop".

    本文标题中的gif已使用我以前的CodeProject文章“ Your Own Avishop ”的程序创建。

    翻译自: https://www.codeproject.com/Articles/5252711/Magic-Formula-of-the-Intersection-Point-of-Two-Lin

    求点到线段交点个数的公式

    展开全文
  • 直接运用两点间距离公式 (x2-x1)^ 2+(y2-y1)^ 2开根号 //两点间距离 double getDistancePP(Point a,Point b) { //这个代码是部分代码,有些逻辑没有展现完全,大家往下看! Point c(b.x-a.x,b.y-a.y);//返回一个新的...

    两点之间的距离

    直接运用两点间距离公式 (x2-x1)^ 2+(y2-y1)^ 2开根号

    //两点间距离
    double getDistancePP(Point a,Point b)
    {
    //这个代码是部分代码,有些逻辑没有展现完全,大家往下看!
        Point c(b.x-a.x,b.y-a.y);//返回一个新的点
        return  c.abs();//取模
    }
    

    点到直线距离

    通常给出3个点,其中两个点构成一条直线,求另外一个点到直线的距离,我们将点与点的关系转换为向量之间关系进而利用向量知识求出点到直线距离!

    点到直线距离,我们可以利用外积的取模公式的几何意义,|axb|=|a|x|b|sinθ=所围成平行四边形面积,先求出向量a✖向量b的模,然后除以平行四边形底边边长|a|,最后用平行四边形面积除以底边边长就是高,也就是点到直线距离!

    图解

    在这里插入图片描述
    不明白外积模的几何意义点击下方超链接
    外积知识点大全

    实现代码

    //点到直线距离(利用外积平行四边形)
    double getDistancePL(Point a,Point b,Point c)
    {
        Vector ab(b.x-a.x,b.y-a.y);
        Vector ac(c.x-a.x,c.y-a.y);
    
        return cross(ab,ac)/ab.abs();//cross函数求两个向量的外积模,abs函数求向量模
    }
    

    点到线段距离

    点到线段距离有一点复杂,因为线段不像直线那样可以无限延申,线段有端点,这就导致了点到线段距离可以分为3种情况!

    第一种:点到线段距离等于点到直线的距离
    图示
    在这里插入图片描述

    第二种:点到线段距离等于点到左端点的距离
    图示
    在这里插入图片描述

    第三种:点到线段等于点到右端点的距离
    图示
    在这里插入图片描述

    如何判断θ大小呢?

    我们利用内积大小判断 a·b=|a|x|b|cosθ
    如果a·b>0则θ在0~90°之间
    如果a·b<0则θ在90°~180°之间

    实现代码

    //点到线段距离
    double getDistancePS(Point a,Point b,Point c)
    {
        //定义4个向量
        Vector ab(b.x-a.x,b.y-a.y);
        Vector ba(a.x-b.x,a.y-b.y);
        Vector ac(c.x-a.x,c.y-a.y);
        Vector bc(c.x-b.x,c.y-b.y);
        //dot函数用于求内积
        if(dot(ab,ac)<0.0) return getDistancePP(a,c);//到左端点距离
        if(dot(ba,bc)<0.0) return getDistancePP(b,c);//到右端点距离
    
        return getDistancePL(a,b,c);//点到直线距离
    }
    
    

    线段到线段距离

    有了点到线段距离,求解线段到线段距离就容易多了!

    首先、两个线段4个端点,我们分别用其中一个线段的一个端点,求出到另外一个线段的距离,在求出另一个端点到线段的距离,在更换线段,依次类推,我们求出4个不同的点到线段的距离,然后取最小值即可!

    在代码中有一点我们暂时不考虑,就是两个线段相交的时候,那么他们的距离应该为0!

    放在下一节学完两条线段相交的判定后直接添加一个if语句即可!

    实现代码

    //线段到线段的距离
    double getDistanceSS(Point a,Point b,Point c,Point d)
    {
        //从4个点到2线段距离中取最小
        return min(min(getDistancePS(c,d,a),getDistancePS(c,d,b)),min(getDistancePS(a,b,c),getDistancePS(a,b,d)));
    }
    

    完整代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    class Point
    {
    
    public:
        double x,y;
    
        Point(double x=0,double y=0):x(x),y(y) {}
    
        //向量加法
        Point operator+(Point p)
        {
            return Point(x+p.x,y+p.y);
        }
        //向量减法
        Point operator-(Point p)
        {
            return Point(x-p.x,y+p.y);
        }
        //向量伸缩
        Point operator*(double a)
        {
            return Point(x*a,y*a);
        }
        Point operator/(double a)
        {
            return Point(x/a,y/a);
        }
        //向量大小
        double abs()
        {
            return sqrt(norm());
        }
        //向量范数
        double norm()
        {
            return x*x+y*y;
        }
    
        bool operator<(const Point &p) const
        {
            return x!=p.x?x<p.x:y<p.y;
        }
    
        bool operator==(const Point &p)const
        {
            return x-p.x<1e-10&&y-p.y<1e-10;
        }
    
    };
    
    typedef Point Vector;
    
    //向量内积
    double dot(Vector a,Vector b)
    {
        return a.x*b.x+a.y*b.y;
    }
    
    //向量外积
    double cross(Vector a,Vector b)
    {
        return abs(a.x*b.y-a.y*b.x);
    }
    
    //正交
    bool isOrthogonal(Vector a,Vector b)
    {
        return a.x*b.x+a.y*b.y==0;
    }
    //平行
    bool isParallel(Vector a,Vector b)
    {
        return a.x*b.y-a.y*b.x==0;
    }
    
    //投影
    Point project(Point a,Point b,Point c)
    {
        Vector ab(b.x-a.x,b.y-a.y);
        Vector ac(c.x-a.x,c.y-a.y);
        double  r=dot(ab,ac)/ab.norm();//比例
        Vector h(ab*r);
        return Point(a.x+h.x,a.y+h.y);
    }
    
    //映象
    
    Point reflect(Point a,Point b,Point c)
    {
        //c到ab的投影点
        Point r=project(a,b,c);
        Vector cr(r.x-c.x,r.y-c.y);
        //cr扩大二倍
        Vector cr_2=cr*2;//上面重载过*
        //向量加法
        return Point(c.x+cr_2.x,c.y+cr_2.y);
    }
    
    //两点间距离
    double getDistancePP(Point a,Point b)
    {
        Point c(b.x-a.x,b.y-a.y);
        return  c.abs();
    }
    
    //点到直线距离(利用外积平行四边形)
    double getDistancePL(Point a,Point b,Point c)
    {
        Vector ab(b.x-a.x,b.y-a.y);
        Vector ac(c.x-a.x,c.y-a.y);
    
        return cross(ab,ac)/ab.abs();
    }
    
    //点到线段距离
    double getDistancePS(Point a,Point b,Point c)
    {
        //定义4个向量
        Vector ab(b.x-a.x,b.y-a.y);
        Vector ba(a.x-b.x,a.y-b.y);
        Vector ac(c.x-a.x,c.y-a.y);
        Vector bc(c.x-b.x,c.y-b.y);
    
        if(dot(ab,ac)<0.0) return getDistancePP(a,c);
        if(dot(ba,bc)<0.0) return getDistancePP(b,c);
    
        return getDistancePL(a,b,c);
    }
    
    
    //线段到线段的距离
    double getDistanceSS(Point a,Point b,Point c,Point d)
    {
        //从4个点到2线段距离中取最小
        return min(min(getDistancePS(c,d,a),getDistancePS(c,d,b)),min(getDistancePS(a,b,c),getDistancePS(a,b,d)));
    }
    int main()
    {
        int x0,y0,x1,y1,x2,y2,x3,y3;
        cin>>x0>>y0>>x1>>y1>>x2>>y2;
        Point a(x0,y0);
        Point b(x1,y1);
        cout<<"a,b两点间距离"<<getDistancePP(a,b)<<endl;
        Point c(x2,y2);
        cout<<"c点到直线ab距离"<<getDistancePL(a,b,c)<<endl;
        
        cout<<"c点到线段ab的距离"<<getDistancePS(a,b,c)<<endl;
        cin>>x3>>y3;
        
        Point d(x3,y3);
        cout<<"线段ab到线段cd的距离"<<getDistanceSS(a,b,c,d)<<endl;
    
        return 0;
    }
    
    

    线段的逆时针方向(顺时针、正上方、正下方、线段上)、相交判断
    –>click–>click

    展开全文
  • 如何求坐标系中两点间的距离

    千次阅读 2021-05-22 04:09:16
    本文收集整理关于如何求坐标系中两点...则有 这与平面直角坐标系中两点间的距离公式是一致的Q2:球坐标系 中两点间距离怎样求转化为直角坐标系,在求两点的距离.Q3:平面直角坐标系中,两点间距离公式两点间的距离公...

    本文收集整理关于如何求坐标系中两点间的距离的相关议题,使用内容导航快速到达。

    内容导航:

    Q1:求任意平面坐标系中两点间的距离公式

    两点间的距离公式: . 其中 、 是复平面内的两点 和 所对应的复数,d表示 和 间的距离. 若 , .则有 这与平面直角坐标系中两点间的距离公式是一致的

    Q2:球坐标系 中两点间距离怎样求

    转化为直角坐标系,在求两点的距离.

    Q3:平面直角坐标系中,两点间距离公式

    两点间的距离公式

    白河一中邓启超

    教学目标与要求

    1、知识与技能:

    (1)使学生掌握平面内两点间的距离公式及推导过程;

    (2)使学生掌握如何建立适当的直角坐标系来解决相应问题。

    2、过程与方法:

    培养学生勇于探索、善于发现、独立思考的能力

    3、情感态度与价值观:

    培养学生不断超越自我的创新品质

    教学重点:

    (1)平面内两点间的距离公式;(2)如何建立适当的直角坐标系

    教学难点:

    如何根据具体情况建立适当的直角坐标系来解决问题

    教学过程:

    第一课时

    一、导入新课

    1.平面上任给两点A,B,通常用表示两点间的距离

    2.已知平面上的两点A(x,y),B(x,y)如何求AB的距离?

    二、新知探究1、提出问题:

    (1)如果A、B是X轴上两点,C、D是Y轴上两点,它们的坐标分别是,那么又怎么样求?

    练习:已知数轴上A、B两点的横坐标x,x分别是

    A:x=8,x=-1;B:x=-4,x=0;C:x=2a-b,x=a-2b

    求和

    (2)求到原点的距离;

    (3)已知平面上的两点,如何求的距离。

    2、解决问题(1)画图形观察可得出:,;

    (2),

    由勾股定理可求得=5

    (3)由图易知

    3、讨论结果

    (1),;

    (2)求到原点的距离是5;

    (3)

    特殊的:当x=x时,;

    当y=y时,三、例题精讲B

    Q4:求 坐标系中两点间的距离

    根号下(x1-x2)^2+(y1-y2)^2

    Q5:空间直角坐标系中两点间的距离怎么求

    有两点间距离公式: 设P1(X1,Y1)、P2(X2,Y2), 则∣P1 P2∣=√[(X1- X2)^2+(Y1- Y2)^2]= √(1+k2) ∣X1 -X2∣, 或者∣P1 P2∣=∣X1 -X2∣secα=∣Y1 -Y2∣/sinα, 其中α为直线P1 P2的倾斜角,k为直线P1 P2的斜率。

    Q6:在直角坐标系中怎样用两点坐标求出这两点之间的距离

    根号下(x1-x2)^2+(y1-y2)^2,(备注这俩个都在根号下,在一起的)

    Q7:平面直角坐标系中求两点间距离的公式是什么?

    把两点作为平面直角坐标系中一个直角三角形的两个顶点,然后用勾股定理求出两点连接后形成的线段长度,即两点间距离

    Q8:平面直角坐标系中,两点间距离公式

    先看在X轴 上的两点之间的距离,高两点的坐标分别是X1和X2,那么两点间距离是|X1-X2|,同理在Y轴上也是一样,即|Y1-Y2| 那么在平面直角坐标系中,任意两点间距离,可以连接两点,再分别过两点作两坐标轴的平行线,这样就构成了一个直角三角形,通过第一段的叙述可以知道两的直角边分别是|X1-X2|,|Y1-Y2|,则利用勾股定理可知,斜边是 根号下(|X1-X2|的平方+|Y1-Y2|的平方)这个就是两点间距离公式。

    展开全文
  • 线段的距离

    千次阅读 2019-10-11 09:18:23
    线段最短距离的运算与到直线的最短距离的运算二者之间存在一定的差别,即求线段最短距离时需要考虑参考在沿线段方向的投影是否在线段上,若在线段上才可采用到直线距离公式,如图1所示。 具体...
  • 线段的最短距离算法

    千次阅读 2019-07-09 11:25:35
    线段最短距离的运算与到直线的最短距离的运算二者之间存在一定的差别,即求线段最短距离时需要考虑参考在沿线段方向的投影是否在线段上,若在线段上才可采用到直线距离公式,如图1所示。 图1(a...
  • 计算机能画一条线段(数学意义上)吗?...已知 x,yx,y 分别为坐标轴上的两点,下式为采样公式, x′=(1−p)⋅x+p⋅y,p∈[0,1] x'=(1-p)\cdot x+p\cdot y,\quad p\in [0, 1] 对 pp在整个 [0,1][0, 1]闭区间上
  • 计算线段的最短距离

    热门讨论 2013-04-09 17:42:49
    这个计算线段最短距离算法是先计算线段上距离最近的,然后求出 2 距离。在计算用户到当前位置到某条公路的最短距离等实际情况中,可以先用这个算法,然后根据结果坐标使用 CLLocation 类的函数计算实际...
  • 编程实现了如何判断一个平面里的线段是否相交!
  • 线段的最短距离

    2020-12-17 19:39:44
    http://blog.sina.com.cn/s/blog_5d5c80840101bnhw.html线段最短距离的运算与到直线的最短距离的运算二者之间存在一定的差别,即求线段最短距离时需要考虑参考在沿线段方向的投影是否在线段上,若在...
  • 空间直线距离公式(文档篇).doc空间直线距离公式(文档8篇)以下是网友分享的关于空间直线距离公式的资料8篇,希望对您有所帮助,就爱阅读感谢您的支持。第一篇38高等数学研究 Vo.l9,No.2...
  • 计算线段的距离

    2021-02-24 13:03:12
    线段的最短距离 起因:在shadertoy看到有人这样画一个线段: float DistLine(vec2 p, vec2 a, vec2 b) { vec2 pa = p-a; vec2 ba = b-a; float t = clamp(dot(pa, ba)/dot(ba, ba), 0.,1.); //float t = ...
  • 代码实现 求线段的最短距离

    千次阅读 2019-05-30 16:22:07
    线段最短距离的运算与到直线的最短距离的运算二者之间存在一定的差别,即求线段最短距离时需要考虑参考在沿线段方向的投影是否在线段上,若在线段上才可采用到直线距离公式,如图1所示。 1、方法...
  • 一种线段的最短距离的方法

    千次阅读 2019-08-20 11:37:25
    一种点到线段的最短距离的方法 ...直线方程由经过两点A (x1,y1) 和 C (x2,y2)确定: B = A + u (C - A) (1-9) 其中u为0到1之间的值,线段AC上的点B (x,y)是最靠近D的点,并且满足下面关系: (D - B) ...
  • 线段的距离 计算几何

    千次阅读 2018-07-19 21:27:16
    线段的距离有种可能,如果线段的垂直线与线段所在直线的交点在线段上,所求的距离就是线段的距离 如果是在射线上,就是到射线一端的距离...
  • 线段最短距离的运算与到直线的最短距离的运算二者之间存在一定的差别,即求线段最短距离时需要考虑参考在沿线段方向的投影是否在线段上,若在线段上才可采用到直线距离公式,如图1所示。+ 图1(a...
  • 线段的距离计算方法

    千次阅读 2019-09-23 17:11:03
    C到线段AB的距离计算有以下几种计算方法 和到直线的距离计算方式不一样,直线是无限延伸的所以直接计算即可,但由于线段的位置不确定,所以我们不管使用何种办法都需要判断线段的位置关系,其存在以下...
  • 计算两点间的球面距离/****a点经度,a点纬度,b点经度,b点纬度**/publicstaticdoublecalcP2P(doublealon,doublealat,doubleblon,doubleblat){doubleR=6378.137;//地球半径(千米)//判断点是在北半球还是南半球,本程序...
  • java计算两点间的距离方法总结

    千次阅读 2021-03-09 00:10:56
    //引用awt包下的Point类,此类的功能是表示 (x,y) 坐标空间中的位置的public class Distance {public static void main(String[] args) {Point p1 = new Point(5, 6);// 定义第一个的坐标(5,6)Point p2 = new...
  • 线段的距离 题解(C++)

    千次阅读 2020-08-05 22:12:28
    对于任意线段l,在其个端点上分别作垂直于l的直线,若直线之间,则称在“线段范围内”,否则在“线段范围外”。 这条直线(蓝色的条)称为“线段范围界线”。 上图中,A在线段范围内,B和C都...
  • /*回顾一下数学公式两点的坐标是(x1, y1)和(x2, y2)则两点之间的距离公式为 d=√[(x1-x2)²+(y1-y2)²]注意特例:当x1=x2时两点间距离为|y1-y2|当y1=y2时两点间距离为|x1-x2|中点坐标:midpoint(X,Y)X=(X1+X2)/2Y=...
  • // 点到直线的最短距离的判断 点(x0,y0) 到由两点组成的线段(x1,y1) ,( x2,y2 ) private double pointToLine(int x1, int y1, int x2, int y2, int x0, int y0) { double space = 0; double a, b, c; a...
  • 判断合并线段 说明全都在注释里了,有的方法可能不是最佳,欢迎大家提出建议~~ public class Line : MonoBehaviour { Vector2 impossiblePoint = -1000 * Vector2.one; // ------...
  • private double pointToLine(int x1, int y1, int x2, int y2, int x0,int y0) {double space = 0;double a, b, c;...// 线段的长度b = lineSpace(x1, y1, x0, y0);// (x1,y1)到点的距离c = lineSp...
  • 经过两点之间经纬度计算直线距离,两种方法皆可用
  • A本身无限长,假设B也无限长,直接求得AB的交点坐标,然后再判断该坐标是否在定长线段B的内部就可以了啊 ... A的两点为(x1,y1),(x2,y2)  则A的直线方程为l1:y-y1=(y2-y1)(x-x1)/(x2-x1)  
  • c# 计算线段的距离

    千次阅读 2020-08-20 15:03:57
    //计算线段的距离 public double pointToLine(Vector2 point,LineBase line) { //距离 double distance =0; //线段的起点与终点 Vector2 start = new Vector2(line.startpoint.x,line.startpoint.z); ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 19,007
精华内容 7,602
关键字:

两点之间线段公式