public function relativeTo($directory, $cwd = null)
	{
		$dir = Path::info($directory);
		if ($dir->isEmpty()) {
			throw new \InvalidArgumentException('Directory is empty.');
		}
		$dir = $dir->normalize()->assumeDirectory();
		$self = $this->normalize()->dir();
		
		if (! $dir->isAbsolute() && is_null($cwd)) {
			throw new \InvalidArgumentException(sprintf('Directory "%s" is not absolute, you have to provide a working directory.', $directory));
		}
		if (! $self->isAbsolute() && is_null($cwd)) {
			throw new \InvalidArgumentException(sprintf('Path "%s" is not absolute, you have to provide a working directory.', $this));
		}
		if (! is_null($cwd)) {
			$cwd = Path::info($cwd)->normalize()->assumeDirectory();
			if (! $cwd->isAbsolute()) {
				throw new \InvalidArgumentException(sprintf('Working directory "%s" must be absolute.', $cwd));
			}
			if ($cwd->isEmpty()) {
				throw new \InvalidArgumentException('Working directory is empty.');
			}
			$dir = $dir->abs($cwd)->normalize();
			$self = $self->abs($cwd)->normalize();
		}
		
		$i = 0;
		while ($i < $dir->partCount && $i < $self->partCount && $dir->parts[$i] === $self->parts[$i]) {
			$i ++;
		}
		$remainder = new Path('');
		$remainder->setParts(array_slice($self->parts, $i));
		$outsideDepth = $dir->partCount - $i - 1;
		if ($outsideDepth > 0) {
			$traversal = array_fill(0, $outsideDepth, '..');
			$remainder->setParts(array_merge($traversal, $remainder->parts));
		}
		$result = $remainder->resolve($this->filename());
		return $result->isEmpty() ? new Path('./') : $result;
	}