Go: package main

import (
	"bufio"
	"os"
	"strconv"
	"strings"
	"fmt"
)

var scanner = bufio.NewScanner(os.Stdin)

func main() {
	scanner.Scan()
	n, _ := strconv.Atoi(scanner.Text())
	for i := 0; i < n; i++ {
		scanner.Scan()
		input := strings.Split(scanner.Text(), " ")
		buf := make([]float64, len(input))
		for j := range buf {
			buf[j], _ = strconv.ParseFloat(input[j], 64)
		}
		p1 := complex(buf[0], buf[1])
		p2 := complex(buf[2], buf[3])
		p3 := complex(buf[4], buf[5])
		pk := complex(buf[6], buf[7])
		ps := complex(buf[8], buf[9])
		kin := isAtSameSide(p3, pk, []complex128{p1, p2}) &&
			isAtSameSide(p1, pk, []complex128{p2, p3}) &&
			isAtSameSide(p2, pk, []complex128{p3, p1})
		sin := isAtSameSide(p3, ps, []complex128{p1, p2}) &&
			isAtSameSide(p1, ps, []complex128{p2, p3}) &&
			isAtSameSide(p2, ps, []complex128{p3, p1})
		if (kin || sin) && !(kin && sin) {
			fmt.Println("OK")
		} else {
			fmt.Println("NG")
		}
	}
}

func isAtSameSide(a, b complex128, line []complex128) bool {
	sa := (real(line[1]) - real(line[0]))*(imag(a)-imag(line[0]))+
		(imag(line[1])-imag(line[0]))*(real(line[0])-real(a))
	sb := (real(line[1]) - real(line[0]))*(imag(b)-imag(line[0]))+
		(imag(line[1])-imag(line[0]))*(real(line[0])-real(b))
	return (sa > 0 && sb > 0) || (sa < 0 && sb < 0)
}

C++: #include<cmath>
#include<algorithm>
#include<iostream>
#include<vector>
 
using namespace std;
 
double EPS = 1e-10;
 
double add(double a, double b){
  if(abs(a+b) < EPS * (abs(a)+abs(b)))return 0;
  return a+b;
}
 
struct point{
  double x, y;
  point(){}
  point(double x,double y) : x(x) , y(y){}
 
  point operator + (point p){
    return point(add(x,p.x), add(y,p.y));
  }
 
  point operator - (point p){
    return point(add(x,-p.x), add(y,-p.y));
  }
 
  point operator * (double d){
    return point(x*d,y*d);
  }
};
 
struct segment{
  point a,b;
};
 
double dot(point a, point b) {
  return (a.x * b.x + a.y * b.y);
}
 
double cross(point a, point b) {
  return (a.x * b.y - a.y * b.x);
}
 
int is_intersected_ls(point a1, point a2, point b1, point b2) {
  return ( cross(a2-a1, b1-a1) * cross(a2-a1, b2-a1) < EPS ) &&
         ( cross(b2-b1, a1-b1) * cross(b2-b1, a2-b1) < EPS );
}

 double vec_abs(point a){
  return sqrt(a.x*a.x+a.y*a.y);
}

int ccw(point p0, point p1, point p2){
  point a = p1 - p0;
  point b = p2 - p0;
  if(cross(a,b)>EPS)return +1;
  if(cross(a,b)<EPS)return -1;
  if(dot(a,b)<-EPS)return +2;
  if(a.x*a.x+a.y*a.y<b.x*b.x+b.y*b.y)return -2;
  return 0;
}
 
vector<segment> construct_edge(point* p, int n){
  vector<segment>seg,seg2;
   
  for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
      if(i!=j){
    segment temp;
    temp.a=p[i];
    temp.b=p[j];
    seg.push_back(temp);
      }
    }
  }
 
  int t=seg.size();
  for(int i=0;i<t;i++){
    int fg=0;
    for(int j=0;j<t;j++){
  if(i!=j && vec_abs(seg[i].b-seg[j].a)<=EPS){
    if(ccw(seg[i].a,seg[i].b,seg[j].b)==1){
      fg=1;
      break;
    }
      }
    }
    if(!fg)seg2.push_back(seg[i]);
  }
  return seg2;
}
 
int point_contain(vector<segment> ps, point p, int n){
  int cnt=ccw(ps[0].a,ps[0].b,p);
 
  for(int i=0;i<n;i++)
    if(cnt!=ccw(ps[i].a,ps[i].b,p))return 0;
   
  return 1;
}
 
int main(void){
  int n;
  point p[3],k,s;
  vector<segment>seg;
 
  cin >> n;
  while(n--){
    for(int i=0;i<3;i++)
      cin >> p[i].x >> p[i].y;
     
    cin >> k.x >> k.y >> s.x >> s.y;
 
    seg=construct_edge(p,3);
 
    if(point_contain(seg,k,3)!=point_contain(seg,s,3))cout << "OK" << endl;
    else cout << "NG" << endl;
     
  }
 
  return 0;
}

C++: //二次元幾何ライブラリ
#include <iostream>
#include <complex>
#include <map>
#include <vector>

using namespace std;

#define rep(i, n) for (int i = 0; i < int(n); ++i)
#define x(a) (a).real()
#define y(a) (a).imag()
typedef long double D;
typedef bool B;
typedef complex<D> P;   //点
typedef complex<D> V;   //ベクトル
typedef pair<P,P>  L;   //直線
typedef pair<P,D>  C;   //円
typedef vector<P>  Pol; //多角形

//変数名定義
const D INF = 1e100;
const D EPS = 1e-8;
const D PI = acos(-1);

template<class T> bool operator==(T a, T b){return abs(a - b )< EPS;}
template<class T> int sig(T r) {return (r==0||r==-0) ? 0 : r > 0 ? 1 : -1;}

  bool operator < (const P& a, const P& b) {
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }

// ベクトルaの絶対値を求める
// D Length = abs(a);

// 2点a,b間の距離を求める
// D Distance = abs(a-b); 

// 内積 (Inner Product) : a・b = |a||b|cosθ
D IP(V a, V b) {
	return (a.real() * b.real() + a.imag() * b.imag());
}

// 外積 (Exterior Product) : a×b = |a||b|sinθ
D EP(V a, V b) {
	return (a.real() * b.imag() - a.imag() * b.real());
}

// 2直線の直交判定 : a⊥b <=> IP(a, b) = 0
B IsVecular(P a1, P a2, P b1, P b2) {
	return IP(a1-a2, b1-b2)==0.0;
}

// 2直線の平行判定 : a//b <=> EP(a, b) = 0
B IsParallel(P a1, P a2, P b1, P b2) {
	return EP(a1-a2, b1-b2)== 0.0;
}


// 点と直線の距離 (Distance of Point and Line)  //l1の構造 x座標 first<second y座標 first>second 右上 正 左下 負 一致の
D  DPL(P p,L l){
	V v1=(p-l.first);
	V v2=(l.second-l.first);
	return EP(v1,v2)/abs(v1);
}

// 三角形の領域判定 Teritory of Triangle 内部のみ
B TT(P p1,P p2,P p3,P p){
	L l1,l2,l3;
	l1=make_pair(p2,p3);
	l2=make_pair(p3,p1);
	l3=make_pair(p1,p2);

	if(sig(DPL(p1,l1))!=sig(DPL(p,l1)))
		return false;
	else if(sig(DPL(p2,l2))!=sig(DPL(p,l2)))
		return false;
	else if(sig(DPL(p3,l3))!=sig(DPL(p,l3)))
		return false;
	else
		return true;
}


//変数名 = 型 代入したいもの
//example : v1 = V(5.0,-3.0) p1=P(0.0,4.0)
int main(void){
	int n;
	cin >>n; 
	rep(i,n){
		P point[5];	
		rep(j,5)
		cin >> point[j].real() >> point[j].imag() ;
		if (TT(point[0],point[1],point[2],point[3])==TT(point[0],point[1],point[2],point[4]))
			cout << "NG" << endl;
		else
			cout << "OK" << endl;
	}
	return 0;
}

C++: #include <iostream>
#include <complex>
#include <sstream>
#include <string>
#include <algorithm>
#include <deque>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <vector>
#include <set>
#include <limits>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;
#define REP(i, j) for(int i = 0; i < (int)(j); ++i)
#define FOR(i, j, k) for(int i = (int)(j); i < (int)(k); ++i)
#define SORT(v) sort((v).begin(), (v).end())
#define REVERSE(v) reverse((v).begin(), (v).end())
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
typedef complex<double> P;
typedef vector<P> G;

double cross(const P& a, const P& b) { return imag(conj(a)*b); }
double dot(const P& a, const P& b) { return real(conj(a)*b); }

enum { OUT, ON, IN };
int contains(const G &g, const P &p) {
  bool in = false;
  for (int i = 0; i < g.size(); ++i) {
    P a = curr(g,i) - p, b = next(g,i) - p;
    if (imag(a) > imag(b)) swap(a, b);
    if (imag(a) <= 0 && 0 < imag(b))
      if (cross(a, b) < 0) in = !in;
    if (cross(a, b) == 0 && dot(a, b) <= 0) return ON;
  }
  return in ? IN : OUT;
}

void input(P &p){
  int x, y; cin >>x >>y;
  p = P(x, y);
}

int main() {
  int N; cin >>N;
  while(N--){
    G g(3);
    REP(i, 3) input(g[i]);
    P a, b;
    input(a); input(b);
    int ac = contains(g, a), bc = contains(g, b);
    cout <<(ac == bc ? "NG" : "OK") <<endl;
  }
  return 0;
}