#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <vector>
using namespace std;

constexpr double EPS = 1e-8;

template<class T> inline void chmax(T &a, const T &b) { if(a < b) a = b; }
template<class T> inline void chmin(T &a, const T &b) { if(a > b) a = b; }

struct point {
	double x, y;
	explicit point(double x_ = 0.0, double y_ = 0.0):x(x_), y(y_) {}

	point operator+(const point &p) const {
		return point(x + p.x, y + p.y);
	}

	point operator-(const point &p) const {
		return point(x - p.x, y - p.y);
	}

	point operator*(double s) const {
		return point(x * s, y * s);
	}

	point operator/(double s) const {
		return point(x / s, y / s);
	}
};

double dot(const point &a, const point &b) {
	return a.x * b.x + a.y * b.y;
}

double cross(const point &a, const point &b) {
	return a.x * b.y - a.y * b.x;
}

double norm(const point &p) {
	return p.x * p.x + p.y * p.y;
}

double abs(const point &p) {
	return sqrt(norm(p));
}

int ccw(const point &a, point b, point c) {
	b = b - a;
	c = c - a;
	const double tmp = cross(b, c);
	if(tmp > EPS) return 1; // ccw
	if(tmp < -EPS) return -1; // cw
	if(dot(b, c) < 0) return 2; // c, a, b 順に一直線上
	if(norm(b) < norm(c)) return -2; // a, b, c 順に一直線上
	return 0; //a, c, b 順で一直線上
}

typedef vector<point> polygon;

struct segment {
	point a, b;
	segment(const point &a_, const point &b_):a(a_), b(b_) {}
};

bool intersect(const segment &s, const point &p) {
	return ccw(s.a, s.b, p) == 0;
}

bool intersect(const segment &s, const segment &t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0
		&& ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

point crosspoint(const segment &s, const segment &t) {
	const double tmp = cross(s.b - s.a, t.b - t.a);
	if(abs(tmp) < EPS) { // 一直線上
		if(intersect(s, t.a)) return t.a;
		if(intersect(s, t.b)) return t.b;
		if(intersect(t, s.a)) return s.a;
		return s.b;
	}
	return t.a + (t.b - t.a) * (cross(s.b - s.a, s.b - t.a) / tmp);
}

double dist(const segment &s, const point &p) {
	if(dot(s.b - s.a, p - s.a) < 0) return abs(p - s.a);
	if(dot(s.a - s.b, p - s.b) < 0) return abs(p - s.b);
	return abs(cross(s.b - s.a, p - s.a)) / abs(s.b - s.a);
}

bool contain(const polygon &P, const point &p) {
	bool res = false;
	point prev = P.back();
	for(const auto &curr : P) {
		point v1 = prev - p, v2 = curr - p;
		if(v1.y > v2.y) swap(v1, v2);
		if(v1.y < EPS && EPS < v2.y && cross(v1, v2) > EPS) res = !res;
		if(abs(cross(v1, v2)) < EPS  && dot(v1, v2) < EPS) return true;
		prev = curr;
	}
	return res;
}

double dist(const polygon &P, const point &p) {
	double res = INT_MAX;
	point prev = P.back();

	for(const auto &curr : P) {
		chmin(res, dist(segment(curr, prev), p));
		prev = curr;
	}

	return res;
}

double ternary_search(double L, double R, const function<double(double)> &f) {
	for(int i = 0; i < 60; ++i) {
		double x1 = (L + L + R) / 3.0, x2 = (L + R + R) / 3.0;
		if(f(x1) < f(x2)) {
			L = x1;
		}
		else {
			R = x2;
		}
	}
	return f(L);
}

double search_y(double x, const polygon &P) {
	const segment L(point(x, 0), point(x, 10000));
	vector<double> range;

	point prev = P.back();
	for(const auto &curr : P) {
		const segment s(prev, curr);
		if(intersect(L, s)) range.emplace_back(crosspoint(L, s).y);
		prev = curr;
	}

	sort(range.begin(), range.end());
	range.erase(unique(range.begin(), range.end()), range.end());

	if(range.size() == 0) return -1;
	return ternary_search(range.front(), range.back(), [&](double y){ return dist(P, point(x, y)); });
}

double search_x(const polygon &P) {
	double L = INT_MAX, R = 0;
	for(const auto &e : P) {
		chmin(L, e.x);
		chmax(R, e.x);
	}
	return ternary_search(L, R, [&](double x){ return search_y(x, P); });
}

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	cout.setf(ios::fixed);
	cout.precision(6);

	for(int n; cin >> n && n;) {
		polygon P(n);
		for(auto &e : P) cin >> e.x >> e.y;
		cout << search_x(P) << endl;
	}

	return EXIT_SUCCESS;
}

Measured memory_bytes: 1320