// TODO: This is hacky. Look into using a library like gojsonpointer[1] instead.
//
// [1] https://github.com/xeipuuv/gojsonpointer
123
func (s *Schema) refToSchema(str string, rootSchema Schema, loadExternal bool) (*Schema, error) {
	parentURL, err := url.Parse(s.parentId)
	if err == nil && parentURL.IsAbs() {
		sURL, err := url.Parse(str)
		if err == nil && !sURL.IsAbs() && !strings.HasPrefix(str, "#") {
			str = parentURL.ResolveReference(sURL).String()
		}
	}

	var split []string
	url, err := url.Parse(str)
	cacheKey, cacheKeyErr := resolveCacheKey(str)
	if err == nil && cacheKeyErr == nil {
		cachedSchema, ok := rootSchema.Cache[cacheKey]
		if ok {
			rootSchema = *cachedSchema
		} else {
			// Handle external URIs.
			if !loadExternal {
				return new(Schema), errors.New("external schemas are disabled")
			}
			resp, err := http.Get(str)
			if err != nil {
				return new(Schema), errors.New("bad external url")
			}
			defer resp.Body.Close()
			s, err := ParseWithCache(resp.Body, loadExternal, &rootSchema.Cache)
			if err != nil {
				return new(Schema), errors.New("error parsing external doc")
			}
			rootSchema.Cache[cacheKey] = s
			rootSchema = *s
		}
		str = url.Fragment
	}

	// Remove the prefix from internal URIs.
	str = strings.TrimPrefix(str, "#")
	str = strings.TrimPrefix(str, "/")

	split = strings.Split(str, "/")
	// Make replacements.
	for i, v := range split {
		r := strings.NewReplacer("~0", "~", "~1", "/", "%25", "%")
		split[i] = r.Replace(v)
	}
	// Resolve the local part of the URI.
	return resolveLocalPath(split, rootSchema, str)
}
1174291
func NewJSONPointerFromString(pointer string) (*JSONPointer, error) {
	if len(pointer) != 0 && pointer[0] != '/' {
		return nil, JSONPointerSyntaxError{pointer}
	}
	bytes := []byte(pointer)
	if at := badEscapeSequence.FindIndex(bytes); at != nil {
		sequence := string(bytes[at[0]:at[1]])
		return nil, BadEscapeSequence{pointer, sequence}
	}
	tokens := strings.Split(pointer, "/")[1:] // remove the leading ""
	for index, token := range tokens {
		tokens[index] = strings.Replace(
			strings.Replace(token, "~1", "/", -1),
			"~0",
			"~",
			-1)
	}
	p := JSONPointer{pointer, tokens}
	return &p, nil
}
1009917
func PointerUp(listener func(*vecty.Event)) *vecty.EventListener {
	return &vecty.EventListener{Name: "pointerup", Listener: listener}
}
1003693
func (mp *MultiPoint) UnmarshalJSON(data []byte) error {
	g := &Geometry{}
	err := json.Unmarshal(data, &g)
	if err != nil {
		return err
	}

	multiPoint, ok := g.Coordinates.(orb.MultiPoint)
	if !ok {
		return errors.New("geojson: not a MultiPoint type")
	}

	*mp = MultiPoint(multiPoint)
	return nil
}
29495
func (p pointer) setPointer(q pointer) {
	*(*unsafe.Pointer)(p.p) = q.p
}
1208518
func pointSide(b orb.Bound, p orb.Point) uint8 {
	if p[1] == b.Max[1] {
		return 4
	} else if p[1] == b.Min[1] {
		return 2
	} else if p[0] == b.Max[0] {
		return 3
	} else if p[0] == b.Min[0] {
		return 1
	}

	return notOnSide
}
1313323
func (f *Fpdf) PointToUnitConvert(pt float64) (u float64) {
	return pt / f.k
}
1271185
func pointInPolygon(x float64, y float64, points []float64) bool {
	if len(points) < 8 { // 只有2个以上的点，才能组成闭合多边形
		return false
	}

	// 大致算法如下：
	// 把整个平面以给定的测试点为原点分两部分:
	// - y>0，包含(x>0 && y==0)
	// - y<0，包含(x<0 && y==0)
	// 依次扫描每一个点，当该点与前一个点处于不同部分时（即一个在 y>0 区，一个在 y<0 区），
	// 则判断从前一点到当前点是顺时针还是逆时针（以给定的测试点为原点），如果是顺时针 r++，否则 r--。
	// 结果为：2==abs(r)。

	r := 0
	x1, y1 := points[0], points[1]
	prev := (y1 > y) || ((x1 > x) && (y1 == y))
	for i := 2; i < len(points); i += 2 {
		x2, y2 := points[i], points[i+1]
		curr := (y2 > y) || ((x2 > x) && (y2 == y))

		if curr == prev {
			x1, y1 = x2, y2
			continue
		}

		mul := (x1-x)*(y2-y) - (x2-x)*(y1-y)
		if mul > 0 {
			r++
		} else if mul < 0 {
			r--
		}
		x1, y1 = x2, y2
		prev = curr
	}

	return r == 2 || r == -2
}
1205657
func FlattenJsonMap(m map[string]interface{}) (map[string][]string, error) {
	outMap := make(map[string][]string, len(m))
	if err := flattenJson("", outMap, m); err != nil {
		return nil, err
	}
	return outMap, nil
}
950265
func structPointer_RefBool(p structPointer, f field) *bool {
	return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
345397
func (p pointer) getPointer() pointer {
	return pointer{p: *(*unsafe.Pointer)(p.p)}
}
1027797
func writePointer(bi *BinaryInfo, mem MemoryReadWriter, addr, val uint64) error {
	ptrbuf := make([]byte, bi.Arch.PtrSize())

	// TODO: use target architecture endianness instead of LittleEndian
	switch len(ptrbuf) {
	case 4:
		binary.LittleEndian.PutUint32(ptrbuf, uint32(val))
	case 8:
		binary.LittleEndian.PutUint64(ptrbuf, val)
	default:
		panic(fmt.Errorf("unsupported pointer size %d", len(ptrbuf)))
	}
	_, err := mem.WriteMemory(uintptr(addr), ptrbuf)
	return err
}
201062
func (l *Line) MarshalJSON() ([]byte, error) {
	return json.Marshal([2]Point{l.a, l.b})
}
419468
func (d *Context) GetPointer(index int) unsafe.Pointer {
	return C.duk_get_pointer(d.duk_context, C.duk_idx_t(index))
}
625101
func ClusterPointers(pointers []geo.Pointer, distancer ClusterDistancer, threshold float64) []*Cluster {
	clusters := make([]*Cluster, 0, len(pointers))
	for _, p := range pointers {
		clusters = append(clusters, NewCluster(p))
	}

	return cluster(clusters, distancer, threshold)
}
526878
func (pTypeDef *Point) UnmarshalJSON(b []byte) error {
	var r rawPoint
	err := json.Unmarshal(b, &r)
	if err == nil {
		o := Point(r)
		*pTypeDef = o
		err = pTypeDef.Validate()
	}
	return err
}
1338489
func (calc *PointCentroidCalculator) AddPoint(point *geom.Point) {
	calc.AddCoord(geom.Coord(point.FlatCoords()))
}