#include <cmath>
#include <vector>
#include <algorithm>

class point2d {
public:
	double x, y;
	point2d() : x(0), y(0) {};
	point2d(double x_, double y_) : x(x_), y(y_) {};
	bool operator==(const point2d& p) { return x == p.x && y == p.y; }
	bool operator!=(const point2d& p) { return x != p.x || y != p.y; }
	point2d& operator+=(const point2d& p) { x += p.x; y += p.y; return *this; }
	point2d& operator-=(const point2d& p) { x -= p.x; y -= p.y; return *this; }
	point2d& operator*=(const double v) { x *= v; y *= v; return *this; }
	point2d operator+(const point2d& p) const { return point2d(*this) += p; }
	point2d operator-(const point2d& p) const { return point2d(*this) -= p; }
	point2d operator*(const double v) const { return point2d(*this) *= v; }
	double norm() const { return x * x + y * y; }
	double abs() const { return std::sqrt(x * x + y * y); }
	double dot(const point2d& p) const { return x * p.x + y * p.y; }
	double cross(const point2d& p) const { return x * p.y - y * p.x; }
	int ccw(const point2d& p1, const point2d& p2) const {
		// RETURNS: P0 -> P1 -> P2 IS COLLINEAR --> ((P0, P1, P2) IS CENTER --> (2, -2, 0)), COUNTER-CLOCKWISE --> 1, CLOCKWISE --> -1
		point2d pr1 = p1 - point2d(*this);
		point2d pr2 = p2 - point2d(*this);
		if (pr1.cross(pr2) != 0) return pr1.cross(pr2) > 0 ? 1 : -1;
		if (pr1.dot(pr2) < 0) return 2;
		return pr1.norm() < pr2.norm() ? -2 : 0;
	}
};
class segment2d {
public:
	point2d p1, p2;
	segment2d() : p1(point2d()), p2(point2d()) {};
	segment2d(const point2d& p1_, const point2d& p2_) : p1(p1_), p2(p2_) {};
	double norm() const { return (p1 - p2).norm(); }
	double abs() const { return (p1 - p2).abs(); }
};

bool intersect(const segment2d& s1, const segment2d& s2) {
	return s1.p1.ccw(s1.p2, s2.p1) * s1.p1.ccw(s1.p2, s2.p2) <= 0 && s2.p1.ccw(s2.p2, s1.p1) * s2.p1.ccw(s2.p2, s1.p2) <= 0;
}
point2d intersect_point(const segment2d& s1, const segment2d& s2) {
	point2d base = s2.p2 - s2.p1;
	double d1 = std::abs(base.cross(s1.p1 - s2.p1));
	double d2 = std::abs(base.cross(s1.p2 - s2.p1));
	return s1.p1 + (s1.p2 - s1.p1) * (d1 / (d1 + d2));
}
double distance(const point2d& p, const segment2d& s) {
	double d1 = (p - s.p1).norm();
	double d2 = (p - s.p2).norm();
	double d0 = s.norm();
	if (d0 + d1 < d2 || d0 + d2 < d1) return std::sqrt(std::min(d1, d2));
	return std::abs((p - s.p1).cross(s.p2 - s.p1)) / std::sqrt(d0);
}

#include <queue>
#include <iostream>
#include <functional>
using namespace std;
struct edge {
	int to, id;
};
int main() {
	int N, M;
	cin >> N >> M;
	vector<segment2d> seg(N);
	for (int i = 0; i < N; ++i) {
		cin >> seg[i].p1.x >> seg[i].p1.y >> seg[i].p2.x >> seg[i].p2.y;
	}
	vector<point2d> valve(M);
	for (int i = 0; i < M; ++i) {
		cin >> valve[i].x >> valve[i].y;
	}
	point2d src, dst;
	cin >> src.x >> src.y >> dst.x >> dst.y;
	vector<vector<int> > cardinals(N);
	vector<point2d> pts;
	vector<int> ptstype;
	function<int(point2d)> next_ptr = [&](point2d p) {
		for (int i = 0; i < pts.size(); ++i) {
			if ((p - pts[i]).abs() < 1.0e-8) return i;
		}
		return int(pts.size());
	};
	for (int i = 0; i < N; ++i) {
		int p1ptr = next_ptr(seg[i].p1);
		if (p1ptr == pts.size()) pts.push_back(seg[i].p1), ptstype.push_back(0);
		cardinals[i].push_back(p1ptr);
		ptstype[p1ptr] |= 1;
		int p2ptr = next_ptr(seg[i].p2);
		if (p2ptr == pts.size()) pts.push_back(seg[i].p2), ptstype.push_back(0);
		cardinals[i].push_back(p2ptr);
		ptstype[p1ptr] |= 1;
	}
	for (int i = 0; i < M; ++i) {
		int ptr = next_ptr(valve[i]);
		if (ptr == pts.size()) pts.push_back(valve[i]), ptstype.push_back(0);
		ptstype[ptr] |= 2;
		for (int j = 0; j < N; ++j) {
			if (distance(valve[i], seg[j]) < 1.0e-8) {
				cardinals[j].push_back(ptr);
			}
		}
	}
	int srcptr = next_ptr(src);
	if (srcptr == pts.size()) pts.push_back(src), ptstype.push_back(0);
	ptstype[srcptr] |= 4;
	int dstptr = next_ptr(dst);
	if (dstptr == pts.size()) pts.push_back(dst), ptstype.push_back(0);
	ptstype[dstptr] |= 8;
	for (int i = 0; i < N; ++i) {
		if (distance(src, seg[i]) < 1.0e-8) {
			cardinals[i].push_back(srcptr);
		}
		if (distance(dst, seg[i]) < 1.0e-8) {
			cardinals[i].push_back(dstptr);
		}
	}
	for (int i = 0; i < N; ++i) {
		for (int j = i + 1; j < N; ++j) {
			if (intersect(seg[i], seg[j])) {
				point2d crp = intersect_point(seg[i], seg[j]);
				int ptr = next_ptr(crp);
				if (ptr == pts.size()) pts.push_back(crp), ptstype.push_back(0);
				ptstype[ptr] |= 16;
				cardinals[i].push_back(ptr);
				cardinals[j].push_back(ptr);
			}
		}
	}
	vector<vector<edge> > G(pts.size());
	int cnt = 0;
	for (int i = 0; i < N; ++i) {
		sort(cardinals[i].begin(), cardinals[i].end(), [&](int j, int k) { return abs(pts[j].x - pts[k].x) > 1.0e-8 ? pts[j].x < pts[k].x : pts[j].y < pts[k].y; });
		cardinals[i].erase(unique(cardinals[i].begin(), cardinals[i].end()), cardinals[i].end());
		for (int j = 1; j < cardinals[i].size(); ++j) {
			G[cardinals[i][j]].push_back(edge{ cardinals[i][j - 1], cnt });
			G[cardinals[i][j - 1]].push_back(edge{ cardinals[i][j], cnt });
			++cnt;
		}
	}
	queue<int> que;
	que.push(dstptr);
	vector<bool> used(pts.size());
	used[dstptr] = true;
	while (!que.empty()) {
		int u = que.front(); que.pop();
		if (ptstype[u] & 2) continue;
		for (edge &e : G[u]) {
			if (!used[e.to]) {
				used[e.to] = true;
				que.push(e.to);
			}
		}
	}
	vector<bool> pass(pts.size());
	vector<bool> usededge(cnt);
	que.push(srcptr);
	pass[srcptr] = true;
	while (!que.empty()) {
		int u = que.front(); que.pop();
		if ((ptstype[u] & 2) && used[u]) continue;
		for (edge& e : G[u]) {
			usededge[e.id] = true;
			if (!pass[e.to]) {
				pass[e.to] = true;
				que.push(e.to);
			}
		}
	}
	if (pass[dstptr]) cout << -1 << endl;
	else {
		double sum = 0.0;
		for (int i = 0; i < pts.size(); ++i) {
			for (edge e : G[i]) {
				if (!usededge[e.id]) {
					sum += (pts[i] - pts[e.to]).abs();
					usededge[e.id] = true;
				}
			}
		}
		cout.precision(15);
		cout << fixed << sum << endl;
	}
	return 0;
}


Measured memory_bytes: 4500