精华内容
下载资源
问答
  • problemId=1265 题意:中文题诶~ 思路:假设现有a, b, c, d四个,若直线 ab, ac, ad线性相关,那么有a...那么我们如何判断是否线性相关呢? 答案很简单,分别以ab, ac, ad的向量坐标作为一个行列式的行(...

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1265

     

    题意:中文题诶~

     

    思路:假设现有a, b, c, d四个点,若直线 ab, ac, ad线性相关,那么有a, b, c, d共线;

    那么我们如何判断其是否线性相关呢? 答案很简单,分别以ab, ac, ad的向量坐标作为一个行列式的行(列)元素,得到一个3阶行式,如果其值为0,则ab, ac, ad线性相关;

    这点很好证明,若ab, ac, ad线性相关则有 ab=k1*ac+k2*ad;

    又因为行列式的性质1:将某行(列)的元素*k,再加到其他行(列)对应元素上行列式的值不变;

           性质2:若行列式有两行(列)的元素相同,那么该行列式的值为0;

    那么很显然我们刚才的结论是正确的啦;

     

    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 struct point{
     5     int x, y, z;
     6 };
     7 
     8 int is_coplanar(point a, point b, point c, point d){
     9     point ab, ac, ad;
    10     ab.x=a.x-b.x, ab.y=a.y-b.y, ab.z=a.z-b.z;
    11     ac.x=a.x-c.x, ac.y=a.y-c.y, ac.z=a.z-c.z;
    12     ad.x=a.x-d.x, ad.y=a.y-d.y, ad.z=a.z-d.z;
    13     int gg=ab.x*ac.y*ad.z+ab.y*ac.z*ad.x+ac.x*ad.y*ab.z;
    14     gg-=ab.z*ac.y*ad.x+ab.x*ac.z*ad.y+ab.y*ac.x*ad.z;
    15     return gg;
    16 }
    17 
    18 int main(void){
    19     int t;
    20     cin >> t;
    21     while(t--){
    22         point a, b, c, d;
    23         cin >> a.x >> a.y >> a.z >> b.x >> b.y >> b.z >> c.x >> c.y >> c.z >> d.x >> d.y >> d.z;
    24         if(!is_coplanar(a, b, c, d)){
    25             cout << "Yes" << endl;
    26         }else{
    27             cout << "No" << endl;
    28         }
    29     }
    30     return 0;
    31 }

     

    转载于:https://www.cnblogs.com/geloutingyu/p/6242913.html

    展开全文
  • 51Nod_1265四点共面

    2018-04-11 15:05:10
    题目要求在控制台输入四个点的坐标(三维),然后判断这四个点是否在同一个平面上。 刚刚看到这个题目的时候有一点懵,静下心来想了想,是不是可以用向量的方式去解决这个问题。因为四个点的坐标已知,由此就可以...

    题目要求在控制台输入四个点的坐标(三维),然后判断这四个点是否在同一个平面上。

        刚刚看到这个题目的时候有一点懵,静下心来想了想,是不是可以用向量的方式去解决这个问题。因为四个点的坐标已知,由此就可以得到由其中三个点组成的两个向量,随后就可以求出与这两个向量垂直的向量,最后用剩下一个点和前面的任意点组成一个向量,只要能与垂直的向量相垂直,就可以得出四点共面的结论。

        可是如何求出与两个向量垂直的向量呢? 我也不知道,所以我去网上看了一下博客,发现这个博客讲的比较好:

    https://blog.csdn.net/hc14519/article/details/50716299

        里面把向量叉积讲的比较清楚,同时我也知道了在三维空间内,两个向量的叉积就是与它们组成的平面垂直的向量。这个问题解决的话,这个问题就比较简单了。话不多说上代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #define maxn 500
    typedef long long int ll;
    using namespace std;
    
    struct Point{
    	ll x,y,z;
    }p[maxn];
    int n;
    ll dMul(Point a,Point b)//求点积
    {
        return a.x * b.x + a.y * b.y + a.z * b.z;
    }
    
    Point xMul(Point a,Point b){
    	Point c;
    	c.x = a.y*b.z-a.z*b.y;
    	c.y = a.z*b.x-a.x*b.z;
    	c.z = a.x*b.y-b.x*a.y;
    	return c;
    }
    Point subPoint(Point a,Point b)
    {
           Point c;
           c.x = a.x - b.x;
           c.y = a.y - b.y;
           c.z = a.z - b.z;
           return  c;
    }
    Point fa(Point a,Point b,Point c){
    	return xMul(subPoint(a,b),subPoint(a,c));
    }
    bool ok(Point a,Point b,Point c,Point d){
    	return dMul(fa(a,b,c),subPoint(a,d))==0;
    }
    
    int main()
    {
    	int T;
    	cin>>T;
    	while(T--){
    		for(int i = 0;i <4;i ++){
    			cin>>p[i].x>>p[i].y>>p[i].z;
    		}
    		if(ok(p[0],p[1],p[2],p[3]))
    			cout<<"Yes"<<endl;
    		else
    			cout<<"No"<<endl;
    	} 
    	return 0;
    }
    
    

        通过代码我们可以看到fa函数是用来获取两个参数向量的法向量的,同时我们写了一个subPoint函数来获取由两个点组成的向量,ok函数是对其他函数的一个封装,所以在控制台只要把四个点作为参数传递给ok函数就可以得到结果。

    注:我们应该注意函数的参数到达指的是一个点,还是一个向量,理解了才能自己用手写出来。

        最后请教了一下实验室的黄学长,得知也可以用矩阵来解决这个问题,把由四个点中的点两两组成的三个向量作为列向量,就可以得到一个矩阵,通过判断矩阵的值是否为0就可以得出四点是否共面,但是其实和求叉积的过程是非常相像的。

        每一天的坚持都在为未来添砖加瓦!

    展开全文
  • 判断AB、CD是否共面,其实就是判断A、B、C、D四个点是否共面。我们知道三点确定一个平面,如果AB垂直于ACD三点所在平面的法线,则说明A、B、C、D四点共面。 A、C、D三点所在平面的法线怎么求? 很简单,两个向量的...


    1 引言

    问题:已知三维空间中四点A、B、C、D,如何判断线段AB与CD是否相交,若相交则求出交点。
    判断AB、CD是否相交并求交点O
    分析:

    • AB、CD要相交,则AB、CD必须要在同一平面内
    • 快速排斥和跨立实验判断是否相交
    • 几何法分析求出交点

    先来看看效果,紫色小球为交点。
    两线段交点效果

    2 求解

    2.1 AB、CD是否共面与平行

    要判断AB、CD是否共面,其实就是判断A、B、C、D四个点是否共面。我们知道三点确定一个平面,如果AB垂直于ACD三点所在平面的法线,则说明A、B、C、D四点共面。
    A、C、D三点所在平面的法线怎么求?
    很简单,两个向量的叉乘就是这两个向量所在平面的法线。
    两个向量的叉乘为这两个向量所在平面的法线
    即ACD平面的法线N\overrightarrow{ N } = CA\overrightarrow{ CA }×CD\overrightarrow{ CD }
    然后又如何判断N\overrightarrow{ N }是否与AB\overrightarrow{ AB }垂直呢?
    如果N\overrightarrow{ N }垂直于AB\overrightarrow{ AB },则它们的夹角为90°,这时我们可以根据N\overrightarrow{ N }AB\overrightarrow{ AB }的点积或者叉积来判断。
    N\overrightarrow{ N }AB\overrightarrow{ AB }
    用点积来判断,则有N\overrightarrow{ N }·AB\overrightarrow{ AB } = |N\overrightarrow{ N }||AB\overrightarrow{ AB }| cos90°\cos90° = 0;
    用叉积来判断,需先把N\overrightarrow{ N }AB\overrightarrow{ AB }化为单位向量,则有|N\overrightarrow{ N }·AB\overrightarrow{ AB }| = |N\overrightarrow{ N }||AB\overrightarrow{ AB }| sin90°\sin90° = 1。
    这里我们用点积来写代码。

    Vector3 ab = b - a;
    Vector3 ca = a - c;
    Vector3 cd = d - c;
    
    Vector3 v1 = Vector3.Cross(ca, cd);
    
    if (Mathf.Abs(Vector3.Dot(v1, ab)) > 1e-6)
    {
        // 不共面
        return false;
    }
    

    AB和CD平行时,两者的夹角为0°或180°,也可用点积或叉积来判断,这里就不再多说了。

    2.2 快速排斥与跨立实验判断AB、CD是否相交

    2.2.1 快速排斥

    快速排斥的作用是先预处理一下,先排出掉根本不可能相交的情况,以减少不必要的运算。
    其原理就是判断AB的包围盒与CD的包围盒是否有重叠的部分。什么意思呢?看图就明白了。
    二维快速排斥
    三维的同理。
    三维快速排斥
    代码怎么写呢?如下。

    // 快速排斥
    if (Mathf.Min(a.x, b.x) > Mathf.Max(c.x, d.x) || Mathf.Max(a.x, b.x) < Mathf.Min(c.x, d.x)
       || Mathf.Min(a.y, b.y) > Mathf.Max(c.y, d.y) || Mathf.Max(a.y, b.y) < Mathf.Min(c.y, d.y)
       || Mathf.Min(a.z, b.z) > Mathf.Max(c.z, d.z) || Mathf.Max(a.z, b.z) < Mathf.Min(c.z, d.z)
    )
        return false;
    

    2.2.2 跨立实验

    什么是跨立呢?比如A、B两点分别位于CD的左右两边,我们就说A、B跨立CD。
    如果两条线段相交,它们必然是互相跨立的嘛。
    怎么判断跨立呢?用向量的叉积。
    如图,AB跨立CD的充要条件是CA\overrightarrow{ CA }×CD\overrightarrow{ CD } · CD\overrightarrow{ CD }×CB\overrightarrow{ CB } > 0。为什么?因为AB跨立CD时,CA\overrightarrow{ CA }×CD\overrightarrow{ CD } 所得法线的方向与CD\overrightarrow{ CD }×CB\overrightarrow{ CB }所得法线的方向是相同的,所以它们两者的点积>0。
    AB跨立CD
    叉积结果的方向是通过右手定则来判定的(为什么是右手定则而不是左手,因为叉积的数学定义就是用的右手),比如CA\overrightarrow{ CA }×CD\overrightarrow{ CD } ,我们拿出右手,大拇指垂直于CA、CD所在平面,然后食指~小指四指从CA弯向CD,此时大拇指的方向即CA\overrightarrow{ CA }×CD\overrightarrow{ CD }的方向(这里是指向屏幕内)。
    代码如下:

    // 跨立试验
    if (Vector3.Dot(Vector3.Cross(-ca, ab), Vector3.Cross(ab, ad)) > 0
        && Vector3.Dot(Vector3.Cross(ca, cd), Vector3.Cross(cd, cb)) > 0)
    {
        // 相交
        return true;
    }
    

    2.3 计算交点

    咱们先写结论。
    结论
    AO与AB的比值求到了,O点也就能求到了。
    结论怎么来的?分析如下:

    ① 咱们先做条辅助线CE,CE平行于AB,且与AB等长。
    做辅助线
    ② 则有ΔAFO相似于ΔEGC,则有
    推导1
    ③ 则有
    推导2
    辅助线2
    ④根据叉积的定义,又有
    推导3
    ⑤于是乎,就有

    推导4
    ⑥我们设v1\overrightarrow{ v1 }=CA\overrightarrow{ CA }×CD\overrightarrow{ CD }v2\overrightarrow{ v2 }=CD\overrightarrow{ CD }×AB\overrightarrow{ AB } ,我们知道v1\overrightarrow{ v1 }v2\overrightarrow{ v2 }的夹角α为0°或180°,
    v1\overrightarrow{ v1 }·v2\overrightarrow{ v2 } = |v1\overrightarrow{ v1 }|·|v2\overrightarrow{ v2 }| cosα\cosα= ±|v1\overrightarrow{ v1 }|·|v2\overrightarrow{ v2 }|,
    就有
    推导6
    这里我们用点积来计算,主要是为了能够求出AB和CD不直接相交,但AB的延长线和CD相交的交点。比如我们把下面提供的代码中的快速排斥和跨立试验给注释掉,就能求出延长线的交点。
    用点乘的目的

    3 完整项目

    如下。

        /// <summary>
        /// 计算AB与CD两条线段的交点.
        /// </summary>
        /// <param name="a">A点</param>
        /// <param name="b">B点</param>
        /// <param name="c">C点</param>
        /// <param name="d">D点</param>
        /// <param name="intersectPos">AB与CD的交点</param>
        /// <returns>是否相交 true:相交 false:未相交</returns>
        private bool TryGetIntersectPoint(Vector3 a, Vector3 b, Vector3 c, Vector3 d, out Vector3 intersectPos)
        {
            intersectPos = Vector3.zero;
    
            Vector3 ab = b - a;
            Vector3 ca = a - c;
            Vector3 cd = d - c;
    
            Vector3 v1 = Vector3.Cross(ca, cd);
    
            if (Mathf.Abs(Vector3.Dot(v1, ab)) > 1e-6)
            {
                // 不共面
                return false;
            }
    
            if (Vector3.Cross(ab, cd).sqrMagnitude <= 1e-6)
            {
                // 平行
                return false;
            }
    
            Vector3 ad = d - a;
            Vector3 cb = b - c;
            // 快速排斥
            if (Mathf.Min(a.x, b.x) > Mathf.Max(c.x, d.x) || Mathf.Max(a.x, b.x) < Mathf.Min(c.x, d.x)
               || Mathf.Min(a.y, b.y) > Mathf.Max(c.y, d.y) || Mathf.Max(a.y, b.y) < Mathf.Min(c.y, d.y)
               || Mathf.Min(a.z, b.z) > Mathf.Max(c.z, d.z) || Mathf.Max(a.z, b.z) < Mathf.Min(c.z, d.z)
            )
                return false;
    
            // 跨立试验
            if (Vector3.Dot(Vector3.Cross(-ca, ab), Vector3.Cross(ab, ad)) > 0
                && Vector3.Dot(Vector3.Cross(ca, cd), Vector3.Cross(cd, cb)) > 0)
            {
                Vector3 v2 = Vector3.Cross(cd, ab);
                float ratio = Vector3.Dot(v1, v2) / v2.sqrMagnitude;
                intersectPos = a + ab * ratio;
                return true;
            }
    
            return false;
        }
    

    项目链接:https://pan.baidu.com/s/1FMi1J9ZuUMnYlz3vH6WETQ
    提取码:o3zq
    博主个人博客本文链接。

    4 参考文章

    文中的方法来自这两篇文章,由衷感谢两位博主。

    展开全文
  • 2.4判断点是否在线段上 2.5判断两线段是否相交 2.6判断矩形是否包含点 2.7判断线段、折线、多边形是否在矩形中 2.8判断矩形是否在矩形中 2.9判断圆是否在矩形中 2.10判断点是否在多边形内 2.10.1射线法 ...
  • 至少有两值得指出: 首先,作者完全采用了一种问答的形式来组织和介绍相关内容。全书从头到尾设计了472个问题(很多是由学生提出来的),有问有答,循序渐进,逐步将各种图像技术依次介绍。这种形式除能帮助...
  • 实例127 利用IsNumeric函数判断是否为数字 实例128 统计某个字符在一个字符串变量中的出现次数 实例129 判断字符串中某一字符是否大写 实例130 判断字符串是否为日期或时间 实例131 判断获得字符串中大写字符的...
  • 实例127 利用IsNumeric函数判断是否为数字 实例128 统计某个字符在一个字符串变量中的出现次数 实例129 判断字符串中某一字符是否大写 实例130 判断字符串是否为日期或时间 实例131 判断获得字符串中大写字符的...
  • asp.net知识库

    2015-06-18 08:45:45
    如何判断ArrayList,Hashtable,SortedList 这类对象是否相等 帮助解决网页和JS文件中的中文编码问题的小工具 慎用const关键字 装箱,拆箱以及反射 动态调用对象的属性和方法——性能和灵活性兼备的方法 消除由try/...
  • 程序开发范例宝典>>

    2012-10-24 10:41:28
    实例227 判断文件是否正在被使用 316 实例228 在程序中调用.HLP文件 317 实例229 C#中实现文件拖放 317 实例230 文件比较 318 实例231 获取文件夹中的图标资源 319 实例232 获取文件夹下的所有...
  • 实例280 判断计算机中是否安装了SQL软件 378 第8章 注册表 380 8.1 个性桌面 381 实例281 禁用桌面选项卡 381 实例282 禁用外观选项卡 382 实例283 禁用屏幕保护选项卡 383 实例284 设置...
  • 实例280 判断计算机中是否安装了SQL软件 378 第8章 注册表 380 8.1 个性桌面 381 实例281 禁用桌面选项卡 381 实例282 禁用外观选项卡 382 实例283 禁用屏幕保护选项卡 383 实例284 设置...
  • 实例280 判断计算机中是否安装了SQL软件 378 第8章 注册表 380 8.1 个性桌面 381 实例281 禁用桌面选项卡 381 实例282 禁用外观选项卡 382 实例283 禁用屏幕保护选项卡 383 实例284 设置...
  • 实例047 判断输入的货币值是否为数字 实例048 对计算结果进行四舍五入 实例049 商品金额的大小写转换 实例050 设置货币值中使用的小数位数 实例051 格式化输入数据为货币格式 实例052 开发一个进制转换器 3.4...
  • 实例047 判断输入的货币值是否为数字 实例048 对计算结果进行四舍五入 实例049 商品金额的大小写转换 实例050 设置货币值中使用的小数位数 实例051 格式化输入数据为货币格式 实例052 开发一个进制转换器 3.4...
  • 实例047 判断输入的货币值是否为数字 实例048 对计算结果进行四舍五入 实例049 商品金额的大小写转换 实例050 设置货币值中使用的小数位数 实例051 格式化输入数据为货币格式 实例052 开发一个进制转换器 3.4...
  • 实例068 高级算法应用——判断IP地址是否合法 105 实例069 高级算法应用——实现裴波纳契数列求和 106 实例070 高级算法应用——求水仙花数的算法 107 实例071 如何将字节单位B转换成GB、MB 和KB 108 实例072 身份证...
  • 实例068 高级算法应用——判断IP地址是否合法 105 实例069 高级算法应用——实现裴波纳契数列求和 106 实例070 高级算法应用——求水仙花数的算法 107 实例071 如何将字节单位B转换成GB、MB 和KB 108 实例072 身份证...
  • 实例068 高级算法应用——判断IP地址是否合法 105 实例069 高级算法应用——实现裴波纳契数列求和 106 实例070 高级算法应用——求水仙花数的算法 107 实例071 如何将字节单位B转换成GB、MB 和KB 108 实例072 身份证...
  • 全书分6篇25章,主要内容有C#开发环境的使用、C#语言基础应用、字符串处理技术、数组和集合的使用、面向对象编程技术、数据结构与算法、Windows窗体基础、特色窗体界面、窗体控制技术、MDI窗体和继承窗体、Windows...
  • 大话数据结构

    2018-12-14 16:02:18
    这样,所谓的判断某一年是否是闰年就变成了查找这个数组的某一项的值是多少的问题。 2.13总结回顾 37 2.14结尾语 38 愚公移山固然可敬,但发明炸药和推土机,可能更加实在和聪明。 第3章线性表 41 3.1开场白 42 ...
  • 2、测试极限时还要注意多种业务接入,本例为ISDN。对于交换机来说,任何一种业务都要分别在模拟话机、ISDN话机、V5话机、多种形式的话务台上做测试。对于中继的业务,则要充分考虑各种信令:TUP、ISUP、PRA、NO1...
  • 交警电子笔录 1.61

    2011-11-17 12:53:17
     51、根据网友意见,修改模板(在笔录每下方加入“?页”);  52、增加“设置”→“设定被询问人到达、离开时间”菜单,通过此菜单可以设置笔录中“口头传唤的被询问人”到达和离开的时间;  53、“资料”→...
  • 单片机核心接受来自键盘扫电路的道德键值,判断是数字键还是操作键,并送相应的处理程序。单片机提供动态扫描电路的显示码和位选信号,使动态显示电路正常工作。 键盘扫电路采用4*4键盘,编号0~9做为数字键“0~9...
  • 12.2.2 判断文件是否存在 224 12.2.3 复制文件 225 12.2.4 删除文件 226 12.2.5 文件的加密和解密 227 12.2.6 文件读取 228 12.3 文件夹类Directory 229 12.3.1 创建文件夹 229 12.3.2 删除文件夹 230 12.3.3 获取...

空空如也

空空如也

1 2
收藏数 34
精华内容 13
关键字:

如何判断点是否共面