详细介绍如何计算两条折线的交点并使用Echarts展示以及图表优化

1、背景

前段时间公司有个需求,需要在一个图表中展示两条折线,并且绘制出两条线的交点。为了满足需求大哥的需求,我也是着实想了有一会。下面我就把具体的实现过程给大家展示一下。

1.1、ECharts 简介

个人很喜欢Echarts这个图表库,就先给大家介绍一下,方便大家更好的了解。

ECharts 是一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等),底层依赖矢量图形库 ZRender,提供直观,交互丰富,可高度个性化定制的数据可视化图表。

ECharts 功能很强大,提供了常见的二维图表,比如折线图、柱图、散点图、饼图、K线图,以及地图、热力图、线图(又称路径图),还有用于表示数据关系的关系图、旭日图等,此外还可以通过GL实现绚丽的三维可视化图。

Echarts 使用起来很方便,展示不同的图表只需要设置简单的配置项;官方的文档写的也很清楚,从简单的实现,到复杂的配置,以及内含的API,应有尽有;除此之外,还有丰富的实例库,以及Echarts的使用者的作品库,很大程度上降低了Echarts的使用门槛,方便初学者使用。而且现在成为了Apache孵化器项目,未来的前景很好。

2、初始绘制图表

需要展示的数据是与日期相关的两条线,每个数据均和一个日期相对应。如下:

// 两条折线图的数据,横坐标是日期,纵坐标为当前日期的数值
    var chartData = {
      line1: ["114", "114", "118", "114", "130", "130", "126", "130", "126", "130", "130", "134", "135", "135", "135", "135", "134", "132", "130", "128", "126", "124", "121", "119", "117", "116", "114", "112", "111", "110", "109", "108", "107", "106", "106", "105", "105", "105", "105", "106", "106", "108", "109", "112", "113", "115", "116", "118", "120", "123", "125", "128", "129", "130", "131", "131", "131", "131", "131", "130", "128", "126", "123", "119", "117", "115", "113", "112", "111", "110", "109", "107", "106", "105", "103", "103", "102", "101", "100", "99", "99", "99", "99", "101", "102", "104", "107", "109", "112", "114", "117", "119", "122", "124", "126", "127", "128", "129", "129", "130", "129", "128", "127", "126", "124", "122", "120", "117", "115", "113", "111", "109", "107", "105", "103", "100", "99", "98", "97", "97", "97", "98", "99", "101", "104", "107", "109", "112", "115", "117", "120", "123", "125", "128", "129", "130", "131", "131", "131", "131", "131", "130", "128", "126", "123", "119", "104"],
      line2: ["124", "124", "128", "124", "140", "140", "136", "140", "136", "140", "140", "136", "132", "128", "128", "124", "124", "120", "116", "112", "112", "112", "112", "112", "108", "108", "108", "104", "108", "104", "104", "100", "104", "104", "108", "104", "108", "104", "108", "112", "116", "120", "124", "128", "124", "120", "124", "128", "132", "136", "140", "140", "136", "132", "128", "128", "124", "124", "120", "116", "112", "108", "104", "100", "104", "108", "112", "116", "112", "108", "104", "100", "96", "92", "88", "92", "96", "100", "100", "104", "104", "108", "112", "116", "116", "116", "120", "120", "124", "132", "132", "132", "132", "136", "132", "132", "128", "128", "124", "124", "120", "120", "116", "116", "112", "108", "108", "104", "104", "104", "100", "96", "96", "92", "92", "88", "92", "96", "100", "104", "108", "112", "116", "120", "124", "128", "124", "120", "124", "128", "132", "136", "140", "140", "136", "132", "128", "128", "124", "124", "120", "116", "112", "108", "104", "100", "103"],
      date: ['200701', '200702', '200703', '200704', '200705', '200706', '200707', '200708', '200709', '200710', '200711', '200712', '200801', '200802', '200803', '200804', '200805', '200806', '200807', '200808', '200809', '200810', '200811', '200812', '200901', '200902', '200903', '200904', '200905', '200906', '200907', '200908', '200909', '200910', '200911', '200912', '201001', '201002', '201003', '201004', '201005', '201006', '201007', '201008', '201009', '201010', '201011', '201012', '201101', '201102', '201103', '201104', '201105', '201106', '201107', '201108', '201109', '201110', '201111', '201112', '201201', '201202', '201203', '201204', '201205', '201206', '201207', '201208', '201209', '201210', '201211', '201212', '201301', '201302', '201303', '201304', '201305', '201306', '201307', '201308', '201309', '201310', '201311', '201312', '201401', '201402', '201403', '201404', '201405', '201406', '201407', '201408', '201409', '201410', '201411', '201412', '201501', '201502', '201503', '201504', '201505', '201506', '201507', '201508', '201509', '201510', '201511', '201512', '201601', '201602', '201603', '201604', '201605', '201606', '201607', '201608', '201609', '201610', '201611', '201612', '201701', '201702', '201703', '201704', '201705', '201706', '201707', '201708', '201709', '201710', '201711', '201712', '201801', '201802', '201803', '201804', '201805', '201806', '201807', '201808', '201809', '201810', '201811', '201812', '201901', '201902', '201903']
    }

下面开始初始绘制图表:

  1. 初始化 echarts 实例。ECharts 图表的展示需要依存在一个设置好 width、height 的 dom 中,Echarts 提供了一个初始化 echarts 实例的方法 echarts.init,此方法返回一个 echarts 实例,后续对图表的设置均是在此实例中实现的。这个方法的第一个参数为 dom,第二个参数设置图表的 theme,第三个参数则是额外的一些配置。一般情况下设置第一个参数即可。
  2. 设置图表的配置项。配置项是一个 js 对象,配置项的解释在下面的代码中,更多的配置可以参考官网。
  3. 绘制图表。echarts 图表的绘制、修改均通过 echarts实例的 setOption 方法完成。此方法可以接受四个参数,第一个为图表的配置项 option,其余三个均为额外的设置。平时使用第一个即可。

代码如下:

<style>
    .charts {
      width: 1000px;
      height: 600px;
    }
</style>
<!-- 准备好一个 dom,并且设置好 width 和 height,后续在此 dom 中绘制图表 -->
<div id="chart" class="charts"></div>
<script>
// 基于准备好的dom,初始化一个 echarts 实例。
var myChart = echarts.init(document.getElementById('chart'));

// 设置图表的配置项
var option = {
  // 标题
  title: {
    text: "初始绘制折线图"
  },
  // 提示框组件,鼠标放置上去后,会展示所在位置信息
  tooltip: {},
  // 图例组件,与 series 中的 name 对应,用于表示不同系列的标记、颜色和名字。也可以通过点击图例控制哪些系列不显示。
  legend: {
    data: ['line1', 'line2']
  },
  // x 轴的配置,默认类型为 type="category" 类目轴。
  xAxis: {
    data: chartData.date // 设置 x 轴的数据
  },
  // y 轴的配置,虽然没有写其他配置,但是必须有,否则会报错
  yAxis: {},
  // 系列列表,一个系列即可理解为一个图表,通过 type 决定所展示的图表类型。
  series: [{
    name: 'line1', // 单个图表系列的 name, 和 legend 中的 data 对应
    type: 'line',
    data: chartData.line1
  }, {
    name: 'line2', // 单个图表系列的 name, 和 legend 中的 data 对应
    type: 'line',
    data: chartData.line2
  }]
}

// 使用数据和配置项展示图表
myChart.setOption(option)
</script>

执行完上面的代码,初始的图表展示就欧克了:

3、计算折线交点

3.1、计算前的准备

计算交点前,需要把数据进行处理,且根据处理的数据,调整图表的展示。

首先,搞一个 计算两个线段交点 的方法,这个方法通过传入 两条线段四个端点横纵坐标 值,来计算两者交点的坐标:

// 求两条线段交点,a,b 为第一条线段的始末点,c,d 为第二条线段的始末点。x,y 为点的横纵坐标
function segmentsIntr({ a, b, c, d } = {}) {
  var denominator = (b.y - a.y) * (d.x - c.x) - (a.x - b.x) * (c.y - d.y)
  var x = ((b.x - a.x) * (d.x - c.x) * (c.y - a.y) +
    (b.y - a.y) * (d.x - c.x) * a.x -
    (d.y - c.y) * (b.x - a.x) * c.x) / denominator
  var y = -((b.y - a.y) * (d.y - c.y) * (c.x - a.x) +
    (b.x - a.x) * (d.y - c.y) * a.y -
    (d.x - c.x) * (b.y - a.y) * c.y) / denominator
  return [x, y]
}

然后传入同一个水平刻度内的两条线段的四个点坐标,不过目前水平刻度所代表的是日期字符串,不适用于计算交点坐标。

所以可以将 x 轴 的数据替换成日期在数组中的序列号 1...n,然后展示 x 轴刻度的时候通过 xAxis 的 formatter 属性,实现自定义刻度,将其转换成对应日期即可。

下面是 xAxis 修改后的配置:

xAxis: {
    // 设置 x 轴的数据, 使用 日期 在数据中的 序列号 来表示 横坐标数值。
    data: chartData.date.map((seg, idx) => {
      return idx
    }),
    // 设置 x 轴的 展示标签, 使其根据 当前标签的序列号转换为 日期
    axisLabel: {
      formatter: function (params) {
        return chartData.date[params]
      }
    }
},

调整后的图表如下:

会发现,X 轴已经好了,但是 提示框 tooltip 还需要再调整一下,那么我们利用 formatter 设置一下 自定义 的 tooltip。通过 formatter 自带参数 params 中的值,拼接好返回的格式即可。

// 提示框组件,鼠标放置上去后,会展示 鼠标 所在位置信息
  tooltip: {
    trigger: 'axis', // 设置提示框为:坐标轴触发。此项主要用于柱图、折线图的配置。
    formatter: function (params) { // params 为一个数组,数组的每个元素 包含了 该折线图的点 所有的参数信息,比如 value(数值)、seriesName(系列名)、dataIndex(数据项的序号)
      let dateIndex = 0; // 当前指示点的 日期序号
      let tipList = params.map((seg) => {
        let { value, seriesName, dataIndex } = seg;
        dateIndex = dataIndex;
        return `${seriesName}:${value}`
      })
      tipList.unshift(`${chartData.date[dateIndex]}`)
      return tipList.join('<br/>')
    }
  },

展示效果如下:

这下子 tooltip 的格式调整好了,不过样式有点怪,原来是 tooltip 缺少了 系列名 前面的 小圆点dot

搞个生成 小圆点dot 的方法:

//获取tooltip的dot,radius 为圆点半径,color 为圆点颜色
function getTipDot({ radius = 5, color = "red" } = {}) {
  return `<span style='width:${radius * 2}px;height:${radius * 2}px;display:inline-block;border-radius: ${radius}px;background:${color};margin:0px 3px;'></span>`
}

把 tooltip 的配置调整一下,添加对于 dot 的设置:

// 提示框组件,鼠标放置上去后,会展示 鼠标 所在位置信息
  tooltip: {
    trigger: 'axis', // 设置提示框为:坐标轴触发。此项主要用于柱图、折线图的配置。
    // params 为一个数组,数组的每个元素 包含了 该折线图的点 所有的参数信息,
    // 比如 value(数值)、seriesName(系列名)、dataIndex(数据项的序号)、color(系列颜色)
    formatter: function (params) {
      let dateIndex = 0; // 当前指示点的 日期序号
      let tipList = params.map((seg) => {
        let { value, seriesName, dataIndex, color } = seg;
        dateIndex = dataIndex;
        return `${getTipDot({ color })}${seriesName}:${value}` // 添加对于 dot 的配置
      })
      tipList.unshift(`${chartData.date[dateIndex]}`)
      return tipList.join('<br/>')
    }
  },

调整后的效果如下:

3.2、计算交点

遍历数据,取出两条线每两个相邻的点组成线段,利用现有的方法 segmentsIntr 开始计算交点。

不过在计算之前,需要判断当前线段内是否有交点,避免不必要的计算。

// 判断两条线段是否有交点, a1、b1 为两条线在 x1 处的值;a2、b2 为两条线在 x2 处的值;
// 只要不是一条线段的两个点都高于另一个点就会有交点;
function ifHaveIntersectionPoint(a1, b1, a2, b2) {
  return (+a1 > +b1) != (+a2 > +b2)
}

除了判断是否有交点,还需要判断是否是遍历的最后一组数据,因为最后一组数据idx,是不会有idx+1的数据的。

// 是否执行后续的计算 ? 不是最后一个点,且有交点时
function ifCalculatePoint(idx, lth, [a1, b1, a2, b2] = []) {
  return idx !== (lth - 1) && ifHaveIntersectionPoint(a1, b1, a2, b2)
}

执行计算

// 获取两线所有交点
function getIntersectionPoint({ line1, line2, date } = {}) {
  // 交点数组
  var intersectionPointList = []
  date.map((seg, idx) => {
    // 分别是两条线在相邻两处的数值,用于通过比较大小,来确定此段内是否有交点
    var valueGroup = [line1[idx], line2[idx], line1[idx + 1], line2[idx + 1]]
    if (ifCalculatePoint(idx, date.length, valueGroup)) {
      var dotGroup = {
        a: { x: idx, y: line1[idx] },
        b: { x: idx + 1, y: line1[idx + 1] },
        c: { x: idx, y: line2[idx] },
        d: { x: idx + 1, y: line2[idx + 1] }
      }
      // 计算交点的位置
      var intersectionPoint = this.segmentsIntr(dotGroup)
      intersectionPointList.push(intersectionPoint)
    }
  })
  return intersectionPointList;
}

4、绘制交点

通过上面的交点计算,得出的结果如下:

intersectionPointList: [
    [11.4, 134.4],
    [33.5, 106],
    [34.666666666666664, 105.33333333333333],
    [35.25, 105],
    [36.75, 105],
    [37.25, 105],
    [53.4, 130.4],
    [66.2, 112.8],
    [68.33333333333333, 110.66666666666667],
    [78, 100],
    [96, 128],
    [117.4, 97.6],
    [135.4, 130.4]
]

可以看到,计算出来的交点很不规律,大部分是小数,在当前的类目轴上并不能很好的展示。

不过好在,Echarts 可以在同一个直角坐标系中同时绘制多个坐标轴。

我们可以在坐标系中添加一条数值轴类型的x轴,并且用散点图绘制出交点。初始绘制效果如下:

可以看到现在有两条 X 轴,调整一下配置项,隐藏掉上层的 X 轴展示。

// x 轴的配置,默认类型为 type="category" 类目轴。
  xAxis: [{
    // 设置 x 轴的数据, 使用 日期 在数据中的 序列号 来表示 横坐标数值。
    data: chartData.date.map((seg, idx) => {
      return idx
    }),
    // 设置 x 轴的 展示标签, 使其根据 当前标签的序列号转换为 日期
    axisLabel: {
      formatter: function (params) {
        return chartData.date[params]
      }
    }
  },
  // 添加一个x轴用于展示散点图(交点)
  {
    type: 'value',
    min: 0,
    max: chartData.date.length - 1,
    show: false
  }]

如上可见,简单的交点已经算是计算并绘制出来了。但是实在是太丑了,下面我来优化一下。

5、图表美化

5.1、整体基调的确认

因为现在流行深邃科技风(随口一编~),那咱们取色就顺着这个方向去。

设置背景颜色为 #010139,不过这里背景我是使用了一个div当做背景层来搞的。代码如下:

<style>
    .chartsArea {
      width: 1000px;
      height: 600px;
      position:relative;
    }

    .chartsAreaBack{
      background-color: #010139;
      width: 100%;
      height: 100%;
      position: absolute;
      opacity: 0.7;
      top: 0;
    }

    .charts {
      width: 100%;
      height: 100%;
    }
</style>
<div class="chartsArea">
    <div class="chartsAreaBack"></div>
    <!-- 准备好一个 dom,并且设置好 width 和 height,后续在此 dom 中绘制图表 -->
    <div id="chart" class="charts"></div>
</div>

然后调整一下图表里面文字的颜色。

option:{
      ...
      // 设置标题的颜色
      title: {
        text: "设置图表的主基调色",
        textStyle: {
          color: '#fff'
        }
      },
      ...
      // x 轴的配置,默认类型为 type="category" 类目轴。
      xAxis: [{
        // 设置 x 轴的数据, 使用 日期 在数据中的 序列号 来表示 横坐标数值。
        data: chartData.date.map((seg, idx) => {
          return idx
        }),
        // 设置 x 轴的 展示标签, 使其根据 当前标签的序列号转换为 日期
        axisLabel: {
          formatter: function (params) {
            return chartData.date[params]
          },
          color: '#04a5bd',//设置标签的样式
          fontWeight: 'bold'
        }
      },
      // 添加一个x轴用于展示散点图(交点)
      {
        type: 'value',
        min: 0,
        max: chartData.date.length - 1,
        show: false
      }],
      // y 轴配置标签颜色
      yAxis: {
        axisLabel: {
          color: '#04a5bd',
          fontWeight: 'bold'
        }
      }
      ...
}

然后,就是这样了,还是挺丑的哈~

5.2、对坐标轴进行优化

我们可以看到当下的x、y轴以及里面的轴线都很难看,我们再继续调整一下。

x轴调整坐标轴颜色以及刻度线的样式。

// 坐标轴线的颜色调整一下
axisLine: {
  lineStyle: {
    color: '#00386d',
    opacity: 0.6
  }
},
// 坐标轴刻度取消展示
axisTick: {
  show: false
}

y 轴将分割线的颜色调整一下,并且取消y轴主轴线的展示。

splitLine: {
    show: true,
        lineStyle: {
            color: '#00386d',
            opacity: 0.4
        }
    },
    axisLine: {
        show: false
    }

图表的取值靠在上半区,所以我们可以调整一下y轴的展示范围。

scale: true

调整完上面的以后,大概就是这个样子了(我偷偷加了个背景图~)

这样看起来就舒服一点了,不过还得继续调整。

5.3、调整折线图以及散点图的样式

我们先调整一下折线图的线条颜色、宽度以及形状等地方。

{
    name: 'line1', // 单个图表系列的 name, 和 legend 中的 data 对应
    type: 'line',
    symbol:'none', // 取消折线图上圆点的展示
    smooth:true, // 将折线进行平滑展示
    itemStyle: { // 设置折线图颜色
      color: '#6B72E7'
    },
    lineStyle: { // 设置线条的宽度
      width: 0.7,
    },
    data: chartData.line1
  }, {
    name: 'line2', // 单个图表系列的 name, 和 legend 中的 data 对应
    type: 'line',
    symbol:'none',
    smooth:true,
    itemStyle: {
      color: '#E93AC8'
    },
    lineStyle: {
      width: 0.7,
    },
    data: chartData.line2
  }

至于散点图,我想着上升交点以及下降交点的颜色给区分开来,所以需要改造一下前面计算交点的方法。

// 获取两线所有交点
function getIntersectionPoint({ line1, line2, date } = {}) {
  // 交点数组
  var intersectionPointList = []
  date.map((seg, idx) => {
    // 分别是两条线在相邻两处的数值,用于通过比较大小,来确定此段内是否有交点
    var valueGroup = [line1[idx], line2[idx], line1[idx + 1], line2[idx + 1]]
    if (ifCalculatePoint(idx, date.length, valueGroup)) {
      var dotGroup = {
        a: { x: idx, y: line1[idx] },
        b: { x: idx + 1, y: line1[idx + 1] },
        c: { x: idx, y: line2[idx] },
        d: { x: idx + 1, y: line2[idx + 1] }
      }
      // 计算交点的位置
      var intersectionPoint = this.segmentsIntr(dotGroup)
      // 给每个数据拼接第三个值,代表是上升还是下降【新增】
      intersectionPoint = [].concat(intersectionPoint,line1[idx + 1] > line2[idx + 1])
      intersectionPointList.push(intersectionPoint)
    }
  })
  return intersectionPointList;
}

然后,根据得出的值,设置散点图的样式。调整散点图的点形状、颜色。

{
    name: 'scatter',
    type: 'scatter',
    xAxisIndex: 1,
    data: getIntersectionPoint(chartData).map((seg) => {
      return {
        value: seg.slice(0, 2),
        symbol:'pin',
        symbolSize:30,
        itemStyle: {
          // 根据上升还是下降,来设置渐变色
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
            offset: 0,
            color: seg[2]?'#E93AC8':'#6B72E7'
          }, {
            offset: 0.9,
            color: '#08178c'
          }, {
            offset: 1,
            color: '#08178c'
          }], false)
        }
      }
    })
  }

哦!对了,前面忘记改图例的文字颜色,这里补充一下。

legend: {
    data: ['line1', 'line2'],
    textStyle: {
      color: '#fff'
    },
  },

下面看一下效果,感觉是不是像个样了?

6、结语

其实针对这个图表还有很多可以做的地方,我这里只是给出了一个计算图表中两折线交点并绘制的大概方法,以及对于图表进行了一些简单的优化,希望此文章能够帮助你熟悉 Echarts 的用法,能够帮助你解决一些问题那就更好了~

github地址:https://github.com/JHCan333/javascript_practice/tree/master/echarts

我是 JHCan333,公众号:爱生活的前端狗 的作者。公众号专注前端工程师方向,包括但不限于技术提高、职业规划、生活品质、个人理财等方面,会持续发布优质文章,从各个方面提升前端开发的幸福感。关注公众号,我们一起向前走!

原文地址:https://www.cnblogs.com/JHCan333/p/12064492.html

时间: 2024-10-06 00:30:48

详细介绍如何计算两条折线的交点并使用Echarts展示以及图表优化的相关文章

计算两条直线的交点(C#)

从其他地方看到的源码是有问题的. /// <summary> /// 计算两条直线的交点 /// </summary> /// <param name="lineFirstStar">L1的点1坐标</param> /// <param name="lineFirstEnd">L1的点2坐标</param> /// <param name="lineSecondStar"

求平面内两条直线的交点

The  and  coordinates of the point of intersection of two non-vertical lines can easily be found using the following substitutions and rearrangements. Suppose that two lines have the equations  and  where  and  are the slopes (gradients) of the lines

【计算几何】如何计算两个圆的交点坐标

How to calculate two coordinates of the intersection points of two circles? 题目: 给定两个圆的的方程 (x-x1)^2+(y-y1)^2=r1^2, (x-x2)^2+(y-y2)^2=r2^2 求解两个圆的交点坐标. 这种知识是高中的知识了,如果直接联立,由于计算特别暴力所以很难得到正确结果. 事实上,造成这种计算问题的结果是因为消去一个变量后,剩下变量的系数太过复杂. 我们通过更改坐标系的方法来使得另外一个系数变得

Intersecting Lines--POJ1269(判断两条直线的关系 &amp;&amp; 求两条直线的交点)

http://poj.org/problem?id=1269 我今天才知道原来标准的浮点输出用%.2f   并不是%.2lf  所以wa了好几次 题目大意:   就给你两个线段 然后求这两个线段所在的直线的关系  有共线  平行  和相交 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h> #include<math.h> #define N 200

求两条直线的交点

CvPoint GetTwoLineCrossPoint(const int& x1, const int& y1, const int& x2, const int& y2, const int& x3, const int& y3, const int& x4, const int& y4) { //第一条直线的参数 double a0 = y1 - y2; double b0 = x2 - x1; double c0 = x1 * y2

AS3 求两条直线的交点

//粘贴到帧上运行即可 var p1Start:Point = new Point(0,0); var p1End:Point = new Point(50,50); var p2Start:Point = new Point(50,50); var p2End:Point = new Point(100,100); var p:Point = new Point(); trace(checkPoint()) function checkPoint() { if (p1Start.x == p1

求两条直线(线段)的交点

转自: http://blog.csdn.net/dgq8211/article/details/7952825 如图,如何求得直线 AB 与直线 CD 的交点P? 以上内容摘自<算法艺术与信息学竞赛>. 思路就是利用叉积求得点P分线段DC的比,然后利用高中学习的定比分点坐标公式求得分点P的坐标. 看不懂的可以去复习下 定比分点 的知识. 1 #include <math.h> 2 #include <stdio.h> 3 #include <string.h&g

求两个一次函数的交点

Point2f pointIntersection(Point2f p1, Point2f p2, Point2f p3, Point2f p4) { //p1,p2所在一条直线,p3,p4所在一条直线,求两条直线的交点 //p1,p2所成的直线 BOOL flag1=FALSE,flag2=FALSE; Point2f p;//存放最后的交点 float k1,k2,b1,b2; if(p2.x==p1.x)//分母不能为0 p.x=p2.x; else { flag1=TRUE; k1=(p

判断两条直线的位置关系 POJ 1269 Intersecting Lines

两条直线可能有三种关系:1.共线     2.平行(不包括共线)    3.相交. 那给定两条直线怎么判断他们的位置关系呢.还是用到向量的叉积 例题:POJ 1269 题意:这道题是给定四个点p1, p2, p3, p4,直线L1,L2分别穿过前两个和后两个点.来判断直线L1和L2的关系 这三种关系一个一个来看: 1. 共线. 如果两条直线共线的话,那么另外一条直线上的点一定在这一条直线上.所以p3在p1p2上,所以用get_direction(p1, p2, p3)来判断p3相对于p1p2的关